From 364da56f9f02f693794553fe1a860e7c25cc6759 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:21:20 +0300 Subject: [PATCH 01/48] feat(permissions): resolve a named permission-mode token in composition Add the ADR 0365 token table over the two existing mechanisms: each token writes cfg.Posture and the default session mode, now threaded to server.Config.DefaultMode. The operator-tier permissionMode: key folds the same way as posture:, which becomes deprecated with a WARN. Build gains the two admission gates. An allow-all posture with no guardrails checker and no kill-switch refuses to start, naming every fix, and a trust-naming posture on a headless root with no trust source refuses after the trust fold. Headless allow-all roots without trust WARN instead. The headless subagent ask reviewer is on by default for allow-all, resolving through the ask-reviewer slot then the session model, with --subagent-ask-reviewer off as the opt-out. One build-once line reports the token, both halves and their lifetimes, and the checker and reviewer states separately. Tests that build an allow-all deployment now declare --guardrails off, the same explicit choice production requires. Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/adapter/permconfig/permconfig.go | 1 + internal/adapter/permconfig/resolve.go | 36 ++- internal/adapter/permconfig/schema.go | 7 + internal/app/authority_vertical_test.go | 40 +-- internal/app/build.go | 70 ++++- .../app/harness_context_authority_test.go | 2 + .../harness_context_execution_source_test.go | 1 + .../app/harness_context_execution_test.go | 2 + .../app/harness_context_freshness_test.go | 1 + internal/app/harness_context_hybrid_test.go | 1 + .../app/harness_context_principal_test.go | 2 +- .../harness_context_project_policy_test.go | 1 + .../app/harness_context_regression_test.go | 3 +- internal/app/harness_context_restart_test.go | 1 + internal/app/permission_mode.go | 277 ++++++++++++++++++ internal/app/posture.go | 3 + 16 files changed, 418 insertions(+), 30 deletions(-) create mode 100644 internal/app/permission_mode.go diff --git a/internal/adapter/permconfig/permconfig.go b/internal/adapter/permconfig/permconfig.go index 16bf8fb63a..76d9ac0004 100644 --- a/internal/adapter/permconfig/permconfig.go +++ b/internal/adapter/permconfig/permconfig.go @@ -182,6 +182,7 @@ func (c *Config) UnmarshalYAML(node ast.Node) error { "permissions": &c.Permissions, "guardrails": newPermconfigNodePointer(&c.Guardrails), "posture": &c.Posture, + "permissionMode": &c.PermissionMode, "models": newPermconfigNodePointer(&c.Models), "reasoning-effort": &c.ReasoningEffort, "plan-mode-auto-approve": &c.PlanModeAutoApprove, diff --git a/internal/adapter/permconfig/resolve.go b/internal/adapter/permconfig/resolve.go index 5d7e56e320..382038d14c 100644 --- a/internal/adapter/permconfig/resolve.go +++ b/internal/adapter/permconfig/resolve.go @@ -139,6 +139,11 @@ type Resolver struct { // files) out-ranks user-global (first-non-empty keeps CLI). operatorPosture string + // operatorPermissionMode is the OPERATOR-TIER permissionMode: token (ADR 0365), + // captured exactly like operatorPosture: user-global + CLI tiers only, CLI + // first-non-empty wins, a project-tier occurrence is ignored with a WARN. + operatorPermissionMode string + // operatorReasoningEffort is the OPERATOR-TIER reasoning-effort: scalar, // read ONCE at construction from the user-global + CLI tiers ONLY. A // project-tier file's reasoning-effort: key is deliberately IGNORED (operator- @@ -379,6 +384,16 @@ func (r *Resolver) OperatorPosture() string { return r.operatorPosture } +// OperatorPermissionMode returns the operator-tier permissionMode: token +// (user-global + CLI only), or "" when none was configured. Like +// OperatorPosture it never returns a project-tier value. nil-safe. +func (r *Resolver) OperatorPermissionMode() string { + if r == nil { + return "" + } + return r.operatorPermissionMode +} + // OperatorReasoningEffort returns the operator-tier reasoning-effort: scalar // (user-global + CLI only), or "" when none was configured. It is the // SOLE accessor the composition layer uses to read reasoning-effort from config — @@ -734,7 +749,15 @@ func (r *Resolver) loadProjectRules(ws tool.WorkspaceReader) []governance.Rule { // project gate forbids (it reverses here, exactly like guardrails). if strings.TrimSpace(cfg.Posture) != "" { r.diag.Log(context.Background(), port.LevelWarn, - "posture: IGNORING a project-tier posture: scalar (operator-tier only — a project repo cannot raise the automation posture; set posture in your user-global settings.yaml or via --posture)", + "posture: IGNORING a project-tier posture: scalar (operator-tier only — a project repo cannot raise the automation posture; set permissionMode in your user-global settings.yaml or via --permission-mode)", + "file", src.path, "root", ws.Root()) + } + // PermissionMode is OPERATOR-TIER ONLY for the same reason as posture (ADR + // 0365): a repo naming its own permission mode could raise the automation + // posture. + if strings.TrimSpace(cfg.PermissionMode) != "" { + r.diag.Log(context.Background(), port.LevelWarn, + "permissionMode: IGNORING a project-tier permissionMode: scalar (operator-tier only — a project repo cannot choose its own permission mode; set permissionMode in your user-global settings.yaml or via --permission-mode)", "file", src.path, "root", ws.Root()) } // ReasoningEffort is OPERATOR-TIER ONLY, for consistency with @@ -931,6 +954,7 @@ func (r *Resolver) loadUserRules(report *Report) []governance.Rule { r.captureGuardrails(cfg.Guardrails) // Operator-tier posture: same first-non-empty-keeps-CLI discipline as guardrails. r.capturePosture(cfg.Posture) + r.capturePermissionMode(cfg.PermissionMode) // Operator-tier reasoning-effort: same discipline as posture. r.captureReasoningEffort(cfg.ReasoningEffort) // Operator-tier plan-mode-auto-approve (issue #206 Wave 6a): same discipline as posture. @@ -978,6 +1002,7 @@ func (r *Resolver) loadUserRules(report *Report) []governance.Rule { r.captureGuardrails(cfg.Guardrails) // User-global posture: captured only if no higher CLI file already did. r.capturePosture(cfg.Posture) + r.capturePermissionMode(cfg.PermissionMode) // User-global reasoning-effort: same discipline as posture. r.captureReasoningEffort(cfg.ReasoningEffort) // User-global plan-mode-auto-approve (issue #206 Wave 6a): same discipline as posture. @@ -1080,6 +1105,15 @@ func (r *Resolver) capturePosture(p string) { r.operatorPosture = strings.TrimSpace(p) } +// capturePermissionMode records the FIRST operator-tier permissionMode: token, +// with the same CLI-first, operator-tier-only discipline as capturePosture. +func (r *Resolver) capturePermissionMode(p string) { + if r.operatorPermissionMode != "" || strings.TrimSpace(p) == "" { + return + } + r.operatorPermissionMode = strings.TrimSpace(p) +} + // captureReasoningEffort records the FIRST operator-tier reasoning-effort: scalar // seen during construction (CLI files are parsed before user-global, so CLI wins // on first-non-empty). It is called only from loadUserRules — the operator diff --git a/internal/adapter/permconfig/schema.go b/internal/adapter/permconfig/schema.go index 809ff7b5e6..d7a102eeaa 100644 --- a/internal/adapter/permconfig/schema.go +++ b/internal/adapter/permconfig/schema.go @@ -165,6 +165,13 @@ type Config struct { // keeps the CLI/default). The composition layer parses the string; permconfig only // reads the scalar. Posture string `yaml:"posture"` + // PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0365: + // plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets + // the posture and the default session mode together and supersedes the + // deprecated posture: key. Like Posture it is honoured ONLY from the + // user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. + // Empty = absent. The composition layer parses the token. + PermissionMode string `yaml:"permissionMode"` // Models holds operator-tier model bindings. Project-tier models: blocks are // ignored with a warning before nested schema decoding. The TOP `models:` mapping // is parsed STRICTLY (an unknown key like `slotz:` errors), the inner slots/aliases diff --git a/internal/app/authority_vertical_test.go b/internal/app/authority_vertical_test.go index 6ece817145..d3386e2c3c 100644 --- a/internal/app/authority_vertical_test.go +++ b/internal/app/authority_vertical_test.go @@ -46,12 +46,13 @@ func TestAuthorityEvaluator_VerticalSlice(t *testing.T) { mockllm.TextTurn("parent complete"), ) cfg := Config{ - Workspace: workspace, - StoreDir: storeDir, - AgentsDirs: []string{agentsDir}, - MockProvider: provider, - NoSoul: true, - AllowAllTools: true, + Workspace: workspace, + StoreDir: storeDir, + AgentsDirs: []string{agentsDir}, + MockProvider: provider, + NoSoul: true, + AllowAllTools: true, + GuardrailsDisabled: true, } built, err := buildIsolated(t, ctx, cfg) if err != nil { @@ -197,6 +198,7 @@ forbid(principal, action, resource) when { resource.path like "` + filepath.ToSl MockProvider: provider, NoSoul: true, AllowAllTools: true, + GuardrailsDisabled: true, AuthorityEvaluator: "cedar", CedarAuthorityPolicy: policyPath, }) @@ -263,6 +265,7 @@ forbid(principal, action, resource) when { resource.path like "` + filepath.ToSl MockProvider: mockllm.New(mockllm.ToolCallTurn(session.NewToolCall("read", "Read", []byte(`{"path":"review/blocked.go"}`))), mockllm.TextTurn("complete")), NoSoul: true, AllowAllTools: true, + GuardrailsDisabled: true, AuthorityEvaluator: "cedar", CedarAuthorityPolicy: policyPath, }) @@ -305,11 +308,12 @@ func TestAuthorityEvaluator_OwnerlessCompositionUsesLocalEvaluator(t *testing.T) t.Fatalf("write workspace file: %v", err) } built, err := buildIsolated(t, context.Background(), Config{ - Workspace: workspace, - StoreDir: filepath.Join(t.TempDir(), "sessions"), - MockProvider: mockllm.New(mockllm.ToolCallTurn(session.NewToolCall("read", "Read", []byte(`{"path":"README.md"}`))), mockllm.TextTurn("done")), - NoSoul: true, - AllowAllTools: true, + Workspace: workspace, + StoreDir: filepath.Join(t.TempDir(), "sessions"), + MockProvider: mockllm.New(mockllm.ToolCallTurn(session.NewToolCall("read", "Read", []byte(`{"path":"README.md"}`))), mockllm.TextTurn("done")), + NoSoul: true, + AllowAllTools: true, + GuardrailsDisabled: true, }) if err != nil { t.Fatalf("Build: %v", err) @@ -360,6 +364,7 @@ func TestAuthorityEvaluator_OwnerlessCedarSessionFailsClosed(t *testing.T) { MockProvider: mockllm.New(mockllm.ToolCallTurn(session.NewToolCall("read", "Read", []byte(`{"path":"README.md"}`))), mockllm.TextTurn("done")), NoSoul: true, AllowAllTools: true, + GuardrailsDisabled: true, AuthorityEvaluator: "cedar", CedarAuthorityPolicy: policyPath, }) @@ -411,12 +416,13 @@ func assertAuthorityVerticalMetaTarget(ctx context.Context, t *testing.T, worksp storeDir := t.TempDir() cfg := Config{ - Workspace: workspace, - StoreDir: storeDir, - MCPServers: []mcp.ServerConfig{{Name: "slack", URL: mcpURL}}, - MockProvider: mockllm.New(mockllm.TextTurn("unused")), - NoSoul: true, - AllowAllTools: true, + Workspace: workspace, + StoreDir: storeDir, + MCPServers: []mcp.ServerConfig{{Name: "slack", URL: mcpURL}}, + MockProvider: mockllm.New(mockllm.TextTurn("unused")), + NoSoul: true, + AllowAllTools: true, + GuardrailsDisabled: true, } built, err := buildIsolated(t, ctx, cfg) if err != nil { diff --git a/internal/app/build.go b/internal/app/build.go index 93cb352969..7d33e3f674 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -1081,6 +1081,27 @@ type Config struct { // (CLI out-ranks YAML) and resolvePosture WARNs if an alias raised above the // explicit value. Set by the cmd mains alongside Posture. PostureFlagSet bool + // PermissionMode is the raw --permission-mode token (ADR 0365), meaningful only + // when PermissionModeFlagSet. foldPermissionMode resolves it (or the + // operator-tier permissionMode: key) into Posture + DefaultSessionMode; an + // unknown token is a Build error naming the valid set. + PermissionMode string + // PermissionModeFlagSet records an explicit --permission-mode. It out-ranks + // the operator-tier permissionMode: and the deprecated posture: keys. + PermissionModeFlagSet bool + // DefaultSessionMode is the session half of a permission-mode token: the mode + // a CreateSession request that leaves mode unspecified starts in + // (server.Config.DefaultMode). Empty means session.ModeDefault. It is only a + // starting point; a session may later change its own mode. + DefaultSessionMode session.PermissionMode + // permissionModeName is the token the operator chose, for messages. Set by + // foldPermissionMode; empty when only the deprecated surface was used. + permissionModeName string + // askReviewerDefaultOn is set by resolveAskReviewerDefault when the headless + // allow-all default engages the subagent ask reviewer (ADR 0365 decision 6). + askReviewerDefaultOn bool + // askReviewerOptOut records an explicit --subagent-ask-reviewer off. + askReviewerOptOut bool // ReasoningEffort is the OPERATOR-TIER reasoning-effort default: the // neutral vocabulary "" / "auto" (unset — provider default) / "low" / "medium" / // "high" / "xhigh" / "max". It is folded from the operator-YAML reasoning-effort: @@ -1677,7 +1698,10 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // MAX-fold; applyPosture then derives AllowAllTools / LooseChildSubstitution / // the TrustProject floor. cfg.permResolver = buildPermResolver(cfg) - cfg = foldOperatorPosture(cfg) + var modeErr error + if cfg, modeErr = foldPermissionMode(cfg); modeErr != nil { + return nil, modeErr + } cfg = foldOperatorReasoningEffort(cfg) cfg = foldOperatorPlanModeAutoApprove(cfg) cfg = foldOperatorSteer(cfg) @@ -1701,6 +1725,12 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.TrustProject = trust.Trusted narratePosture(cfg.diag(), cfg.Posture, cfg.TrustProject) narrateTrust(cfg.diag(), trust, cfg.Workspace) + // Headless admission gate (ADR 0365): after the trust fold, so every + // legitimate trust source satisfies it. + if err := headlessTrustRefusal(cfg); err != nil { + return nil, err + } + narrateWithheldTrust(cfg) // File-based permission config (issues #13/#32): construct the resolver // EXACTLY ONCE here, right after the trust fold (it consumes the effective @@ -2039,6 +2069,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.SubagentModel = subagentModel // SubagentAskReviewerModel (issue #31): the same fail-fast normalization // posture as SubagentModel — validate the alias once here; empty = reviewer off. + cfg.askReviewerOptOut = isAskReviewerOptOut(cfg.SubagentAskReviewerModel) reviewerModel, err := normalizeAskReviewerModel(cfg) if err != nil { return nil, err @@ -2061,6 +2092,17 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.guardrailModel = guardrailModel cfg.guardrailSource = guardrailSrc cfg.guardrailConfigured = guardrailConfigured + // Allow-all admission gate (ADR 0365): the checker truth is the SAME the + // posture line and the live checker use (the binding, else the resolver). + checkerConfigured := guardrailConfigured + if !checkerConfigured { + _, _, checkerConfigured = resolveGuardrailsCheckerModel(cfg) + } + if err := checkerRefusal(cfg, checkerConfigured); err != nil { + return nil, err + } + cfg = resolveAskReviewerDefault(cfg) + narratePermissionMode(cfg, checkerConfigured) // Emit the build-once composition facts (token counter / compaction strategy / // slash commands) EXACTLY ONCE here, through the injected Diagnostics — keyed to // the resolved MAIN model. The per-derivation builders do not log these (they @@ -2406,6 +2448,10 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { mcpStatus = assets.mcpReconciler.statusSnapshot } svcCfg := server.Config{ + // The session half of the permission-mode token (ADR 0365): the mode a + // CreateSession that leaves mode unspecified starts in. Empty keeps the + // server's own ModeDefault. + DefaultMode: cfg.DefaultSessionMode, BuildID: buildinfo.BuildID, ServerImplementation: cfg.ServerImplementation, // GetServerInfo looks up only a caller-selected, already-known provider @@ -5216,8 +5262,8 @@ func normalizeSubagentModel(cfg Config) (string, error) { // the build-once ACTIVE fact. func normalizeAskReviewerModel(cfg Config) (string, error) { sel := strings.TrimSpace(cfg.SubagentAskReviewerModel) - if sel == "" { - return sel, nil + if sel == "" || isAskReviewerOptOut(sel) { + return "", nil } // FAIL-FAST validation runs FIRST, regardless of reachability: the alias // lookup is free and catches a typo'd --subagent-ask-reviewer at config time @@ -7438,10 +7484,12 @@ func buildAskAdjudicator(cfg Config, provReg *providerRegistry, provider port.LL // reviewer is not configured. func askAdjudicatorDeps(cfg Config, provReg *providerRegistry, provider port.LLMProvider, parentProviderID, parentModel string) (agent.Deps, bool) { sel := strings.TrimSpace(cfg.SubagentAskReviewerModel) - if sel == "" { + if sel == "" && !cfg.askReviewerDefaultOn { // The --subagent-ask-reviewer flag STAYS the enable gate: a slot alone does // NOT turn the reviewer on (a slot only chooses the model for a reviewer the - // operator already enabled). Empty flag ⇒ reviewer off, byte-identical. + // operator already enabled). Empty flag ⇒ reviewer off, byte-identical — + // except the ADR 0365 headless allow-all default (askReviewerDefaultOn), + // which resolves through the slot, then the parent model, below. return agent.Deps{}, false } // ASK-REVIEWER SLOT: a configured `ask-reviewer` slot @@ -7451,11 +7499,13 @@ func askAdjudicatorDeps(cfg Config, provReg *providerRegistry, provider port.LLM reviewerProvider, reviewerProviderID := provider, parentProviderID if slotProvider, slotProviderID, slotModel, ok := resolveAuxiliarySlotTarget(cfg, provReg, slotAskReviewer, provider, parentProviderID, parentModel); ok { reviewerProvider, reviewerProviderID, model = slotProvider, slotProviderID, slotModel - } else if target, err := resolveModelTarget(cfg, parentProviderID, "", sel); err == nil { - model = target.Model - if target.ProviderID != parentProviderID && provReg != nil { - if entry, found := provReg.Lookup(target.ProviderID); found { - reviewerProvider, reviewerProviderID = entry.provider, target.ProviderID + } else if sel != "" { + if target, err := resolveModelTarget(cfg, parentProviderID, "", sel); err == nil { + model = target.Model + if target.ProviderID != parentProviderID && provReg != nil { + if entry, found := provReg.Lookup(target.ProviderID); found { + reviewerProvider, reviewerProviderID = entry.provider, target.ProviderID + } } } } diff --git a/internal/app/harness_context_authority_test.go b/internal/app/harness_context_authority_test.go index 55de94e0f9..3ee5b2d05f 100644 --- a/internal/app/harness_context_authority_test.go +++ b/internal/app/harness_context_authority_test.go @@ -30,6 +30,7 @@ func TestHarnessContext_ChildAttenuationPreserved(t *testing.T) { kinds.AgentDefs = permconfig.HarnessContextKind{Sources: []string{"specialists"}, Mode: "combine"} cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: []string{"context", "specialists"}, Kinds: kinds}) cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true if profile == server.ProfileDefault { cfg.Shell = "/bin/sh" } @@ -233,6 +234,7 @@ func TestHarnessContext_ContextOverridesCannotGrantAuthority(t *testing.T) { cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: []string{"repository", "operator"}, Kinds: kinds}) cfg.TrustProject = trusted cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true data, err := os.ReadFile(cfg.PermissionConfigs[0]) if err != nil { t.Fatal(err) diff --git a/internal/app/harness_context_execution_source_test.go b/internal/app/harness_context_execution_source_test.go index eca58aefab..390868752d 100644 --- a/internal/app/harness_context_execution_source_test.go +++ b/internal/app/harness_context_execution_source_test.go @@ -337,6 +337,7 @@ func testExecutionSourceScheduledRestart(t *testing.T) { var requests []port.LLMRequest cfg := harnessExecutionConfig(t, provider, &requests) cfg.StoreDir, cfg.AllowAllTools, cfg.OwnershipEnforced = storeDir, true, true + cfg.GuardrailsDisabled = true original := cfg.HarnessInstructionSources[0].Bind var unpublished []session.SessionID var resumed atomic.Int32 diff --git a/internal/app/harness_context_execution_test.go b/internal/app/harness_context_execution_test.go index f53d2e912d..7889a1e700 100644 --- a/internal/app/harness_context_execution_test.go +++ b/internal/app/harness_context_execution_test.go @@ -132,6 +132,7 @@ func TestHarnessContext_ExplicitExecutionFileSource(t *testing.T) { cfg := hcConfiguredFiles(t, ws) cfg.PlacementProvider = harnessVirtualPlacement(ws) cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.ToolCall{ID: "read", Name: "Read", Args: json.RawMessage(`{"path":"data.txt"}`)}), mockllm.TextTurn("done")) b, err := buildIsolated(t, t.Context(), cfg) @@ -197,6 +198,7 @@ func TestHarnessContext_SourceReadsDoNotAuthorizeEdits(t *testing.T) { cfg := hcConfiguredFiles(t, ws) cfg.PlacementProvider = harnessVirtualPlacement(ws) cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true cfg.MockProvider = mockllm.New( mockllm.ToolCallTurn(session.ToolCall{ID: "source-only", Name: "Edit", Args: json.RawMessage(`{"path":"AGENTS.md","old_string":"original","new_string":"changed"}`)}), mockllm.ToolCallTurn(session.ToolCall{ID: "read", Name: "Read", Args: json.RawMessage(`{"path":"AGENTS.md"}`)}), diff --git a/internal/app/harness_context_freshness_test.go b/internal/app/harness_context_freshness_test.go index 674ddd32e0..f9bcd7e61b 100644 --- a/internal/app/harness_context_freshness_test.go +++ b/internal/app/harness_context_freshness_test.go @@ -44,6 +44,7 @@ func TestHarnessContext_ProjectInstructionsSessionRetention(t *testing.T) { cfg := hcConfiguredFiles(t, source) cfg.NoSoul = true cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true if err := os.WriteFile(filepath.Join(cfg.Workspace, "data.txt"), []byte("execution"), 0o600); err != nil { t.Fatal(err) } diff --git a/internal/app/harness_context_hybrid_test.go b/internal/app/harness_context_hybrid_test.go index 1b296c096d..b2f88a33c9 100644 --- a/internal/app/harness_context_hybrid_test.go +++ b/internal/app/harness_context_hybrid_test.go @@ -59,6 +59,7 @@ func harnessHybridConfig(t *testing.T, includeRepository bool, instructionMode s } cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: enabled, Kinds: kinds}) cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true deployment := t.TempDir() if err := os.WriteFile(filepath.Join(deployment, "policy.md"), []byte("DEPLOYMENT-INSTRUCTIONS"), 0o600); err != nil { t.Fatal(err) diff --git a/internal/app/harness_context_principal_test.go b/internal/app/harness_context_principal_test.go index b2d62d868a..8ade74ea9c 100644 --- a/internal/app/harness_context_principal_test.go +++ b/internal/app/harness_context_principal_test.go @@ -60,7 +60,7 @@ func TestHarnessContext_PrincipalScopedBindingIsolation(t *testing.T) { binds[index].Add(1) } var requests []port.LLMRequest - cfg := Config{Workspace: t.TempDir(), UserModelDir: t.TempDir(), SoulPath: filepath.Join(t.TempDir(), "soul.md"), PermissionConfigs: []string{file}, UseMock: true, OwnershipEnforced: true, AllowAllTools: true, + cfg := Config{Workspace: t.TempDir(), UserModelDir: t.TempDir(), SoulPath: filepath.Join(t.TempDir(), "soul.md"), PermissionConfigs: []string{file}, UseMock: true, OwnershipEnforced: true, AllowAllTools: true, GuardrailsDisabled: true, MockProvider: mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.NewToolCall("agent-alice", "Subagent", []byte(`{"agent":"owner-agent-alice","prompt":"report owner"}`))), mockllm.TextTurn("alice specialist done"), diff --git a/internal/app/harness_context_project_policy_test.go b/internal/app/harness_context_project_policy_test.go index 3dd47ce6be..1338d6c663 100644 --- a/internal/app/harness_context_project_policy_test.go +++ b/internal/app/harness_context_project_policy_test.go @@ -19,6 +19,7 @@ func TestHarnessProjectPolicyIgnoredValueFreeWithoutDroppingDeny(t *testing.T) { cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{Kinds: harnessEmptyKinds()}) cfg.PermissionsConventional = true cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true cfg.TrustProject = true if err := os.MkdirAll(filepath.Join(cfg.Workspace, ".mecatl"), 0o700); err != nil { t.Fatal(err) diff --git a/internal/app/harness_context_regression_test.go b/internal/app/harness_context_regression_test.go index 355e6388ea..6e6d5b2040 100644 --- a/internal/app/harness_context_regression_test.go +++ b/internal/app/harness_context_regression_test.go @@ -43,12 +43,13 @@ func TestDefaultHarnessInstructionsFlowToChildren(t *testing.T) { {name: "untrusted", profile: server.ProfileDefault, untrusted: true, denyWrite: true}, } { t.Run(tc.name, func(t *testing.T) { - cfg := Config{Workspace: t.TempDir(), UseMock: true, Headless: true, TrustProject: true, AllowAllTools: true, Shell: "/bin/sh", UserModelDir: t.TempDir(), NoSoul: true} + cfg := Config{Workspace: t.TempDir(), UseMock: true, Headless: true, TrustProject: true, AllowAllTools: true, GuardrailsDisabled: true, Shell: "/bin/sh", UserModelDir: t.TempDir(), NoSoul: true} if tc.explicit { kinds := harnessEmptyKinds() kinds.Instructions = permconfig.HarnessContextKind{Sources: []string{"local"}, Mode: "combine"} cfg = harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: []string{"local"}, Kinds: kinds}) cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true cfg.Shell = "/bin/sh" } cfg.TrustProject = !tc.untrusted diff --git a/internal/app/harness_context_restart_test.go b/internal/app/harness_context_restart_test.go index b81e4d8e43..7d9fd3d144 100644 --- a/internal/app/harness_context_restart_test.go +++ b/internal/app/harness_context_restart_test.go @@ -32,6 +32,7 @@ func TestHarnessContext_RestartRebindsCurrentPolicy(t *testing.T) { cfg.MemoryDir = memoryDir cfg.OwnershipEnforced = true cfg.AllowAllTools = true + cfg.GuardrailsDisabled = true cfg.MockProvider = provider cfg.HarnessInstructionSources = []HarnessSourceRegistration[prompt.InstructionAssembler]{{ID: HarnessSourceID(id), Scope: HarnessSourceScopePrincipal, Provenance: HarnessProvenancePolicy{Fixed: "driver"}, Bind: func(_ context.Context, scope HarnessSourceScope) (prompt.InstructionAssembler, func() error, error) { if !scope.Principal.SameIdentity(owner) { diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go new file mode 100644 index 0000000000..5dc91cfe72 --- /dev/null +++ b/internal/app/permission_mode.go @@ -0,0 +1,277 @@ +package app + +import ( + "context" + "fmt" + "strings" + + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/permconfig" +) + +// permission_mode.go is the COMPOSITION-LAYER named permission-mode vocabulary +// (ADR 0365). A token is an operator shorthand that writes an exact pair of +// EXISTING values: the process-wide Posture and the default session +// PermissionMode (server.Config.DefaultMode). It introduces no third source of +// permission state: the table below is the whole mechanism, and it is a lookup, +// not an ordering. Permission relaxation and project trust are independent axes, +// so no total order over the tokens exists and none may be inferred from their +// position in the table. + +// PermissionModeToken is one named combination of posture and default session +// mode. +type PermissionModeToken struct { + // Name is the CLI/YAML spelling. + Name string + // Posture is the process-wide half, fixed at startup. + Posture Posture + // SessionMode is the session half: only the default a new session starts in. + SessionMode session.PermissionMode +} + +// permissionModeTable is the ADR 0365 contract. Redundant products (an +// accept-edits variant of auto or yolo) are deliberately absent: allow-all +// already permits edits. +var permissionModeTable = []PermissionModeToken{ + {Name: "plan", Posture: PostureStrict, SessionMode: session.ModePlan}, + {Name: "default", Posture: PostureStrict, SessionMode: session.ModeDefault}, + {Name: "accept-edits", Posture: PostureStrict, SessionMode: session.ModeAccept}, + {Name: "trusted", Posture: PostureTrusted, SessionMode: session.ModeDefault}, + {Name: "trusted-accept-edits", Posture: PostureTrusted, SessionMode: session.ModeAccept}, + {Name: "auto", Posture: PostureAuto, SessionMode: session.ModeDefault}, + {Name: "yolo", Posture: PostureYolo, SessionMode: session.ModeDefault}, +} + +// PermissionModeNames lists the valid tokens in table order, for help text and +// error messages. +func PermissionModeNames() []string { + names := make([]string, len(permissionModeTable)) + for i, tok := range permissionModeTable { + names[i] = tok.Name + } + return names +} + +// ParsePermissionMode resolves a token. An unknown or empty value is an error +// naming the valid set; unlike the deprecated --posture it never fails closed +// silently, because an operator who typed a mode name must learn it did nothing. +func ParsePermissionMode(s string) (PermissionModeToken, error) { + want := strings.ToLower(strings.TrimSpace(s)) + for _, tok := range permissionModeTable { + if tok.Name == want { + return tok, nil + } + } + return PermissionModeToken{}, fmt.Errorf("unknown permission mode %q: valid values are %s", s, strings.Join(PermissionModeNames(), ", ")) +} + +// PermissionModeForPair returns the token naming (posture, mode), if one exists. +// The deprecated alias surface can produce pairs no token names (for example +// auto with a plan session); those stay expressible and report ok=false. +func PermissionModeForPair(p Posture, mode session.PermissionMode) (PermissionModeToken, bool) { + if mode == "" { + mode = session.ModeDefault + } + for _, tok := range permissionModeTable { + if tok.Posture == p && tok.SessionMode == mode { + return tok, true + } + } + return PermissionModeToken{}, false +} + +// foldPermissionMode applies the permission-mode token BEFORE the posture fold. +// Precedence: an explicit --permission-mode flag, then the operator-tier +// permissionMode: key, then the deprecated surface (--posture/--yolo and the +// operator-tier posture: key, handled by foldOperatorPosture). A token writes +// cfg.Posture and cfg.DefaultSessionMode and marks the posture explicit, so the +// deprecated posture: key cannot override it. --trust-project and --yolo still +// fold MAX-tier on top in resolvePosture, exactly as they do over --posture. +func foldPermissionMode(cfg Config) (Config, error) { + raw := "" + source := "" + switch { + case cfg.PermissionModeFlagSet: + raw, source = cfg.PermissionMode, "--permission-mode" + case cfg.PostureFlagSet: + // An explicit (deprecated) --posture is a CLI flag and out-ranks the + // operator YAML, the rule --posture already follows for posture:. + default: + if res, ok := cfg.permResolver.(*permconfig.Resolver); ok && res != nil { + if v := strings.TrimSpace(res.OperatorPermissionMode()); v != "" { + raw, source = v, "settings permissionMode" + } + } + } + if source == "" { + return foldOperatorPosture(cfg), nil + } + tok, err := ParsePermissionMode(raw) + if err != nil { + return cfg, fmt.Errorf("%s: %w", source, err) + } + cfg.Posture = tok.Posture + cfg.PostureFlagSet = true + cfg.DefaultSessionMode = tok.SessionMode + cfg.permissionModeName = tok.Name + return cfg, nil +} + +// checkerRefusal is the allow-all admission gate (ADR 0365 decision 4). A +// posture that waives the built-in mutate-ask floor leaves the guardrails +// checker as the only inspection of tool content, so starting one with no +// checker and no explicit kill-switch is refused. It keys on the RESOLVED +// posture with no exemption for a flag default; shipped defaults declare their +// choice instead. +func checkerRefusal(cfg Config, checkerConfigured bool) error { + if cfg.Posture < PostureAuto || checkerConfigured || cfg.GuardrailsDisabled { + return nil + } + msg := fmt.Sprintf("permission mode %q allows every tool without asking, but no guardrails checker is configured, so nothing would inspect tool content. Fix it one of three ways: set a checker with --guardrails-model ; bind the `guardrail` model slot (--model-slot guardrail= or models.slots.guardrail in settings.yaml); or run unsupervised on purpose with --guardrails off", + cfg.resolvedPermissionModeName()) + if cfg.Posture >= PostureYolo { + msg += ". " + yoloCheckerAdvisoryNote + } + return fmt.Errorf("%s", msg) +} + +// yoloCheckerAdvisoryNote states what a configured checker does NOT do at the +// gate-free tier, where demoteForPosture makes it advisory. Shared by the +// refusal and the startup line so they cannot disagree. +const yoloCheckerAdvisoryNote = "At yolo a configured checker is observability-only: it has no pre-tool veto, no approve-once human ask, and no fail-closed on checker failure, so a checker outage looks the same as a clean result" + +// headlessTrustRefusal is the headless admission gate (ADR 0365 decision 5). +// It runs AFTER resolveTrust, so any legitimate trust source satisfies it, and +// applies only to the trust-naming posture: trust is not auto's or yolo's +// defining increment, so those WARN instead (narrateWithheldTrust). +func headlessTrustRefusal(cfg Config) error { + if !cfg.Headless || cfg.Posture != PostureTrusted || cfg.TrustProject { + return nil + } + return fmt.Errorf("permission mode %q honours this project's instructions and rules, but a headless root never gains project trust from the permission mode and no trust source is present. Fix it one of three ways: pass --trust-project; add this workspace to trustedWorkspaces in your user-global settings.yaml; or choose a mode that does not name project trust, such as default or auto", + cfg.resolvedPermissionModeName()) +} + +// narrateWithheldTrust WARNs when a headless allow-all root starts without +// project trust: it is a legitimate production state (ADR 0095), but the +// operator should see that project instructions and rules are not loaded. +func narrateWithheldTrust(cfg Config) { + if !cfg.Headless || cfg.Posture < PostureAuto || cfg.TrustProject { + return + } + cfg.diag().Log(context.Background(), port.LevelWarn, + "permission mode: project trust WITHHELD on this headless root; project instructions and rules are not loaded. Pass --trust-project or add the workspace to trustedWorkspaces to load them", + "permission_mode", cfg.resolvedPermissionModeName()) +} + +// resolvedPermissionModeName names the effective pair for messages: the token +// the operator chose, else the token equivalent to the resolved pair, else a +// description of a pair no token names (reachable only via deprecated aliases). +func (cfg Config) resolvedPermissionModeName() string { + if cfg.permissionModeName != "" { + return cfg.permissionModeName + } + if tok, ok := PermissionModeForPair(cfg.Posture, cfg.DefaultSessionMode); ok { + return tok.Name + } + mode := cfg.DefaultSessionMode + if mode == "" { + mode = session.ModeDefault + } + return fmt.Sprintf("posture %s with session mode %s", cfg.Posture, mode) +} + +// checkerState reports the guardrails checker as exactly one of three named +// states (ADR 0365 AC2.6), plus the reason when it is disabled. +func checkerState(cfg Config, configured bool) (state, reason string) { + switch { + case cfg.GuardrailsDisabled: + return "disabled", "kill-switch (--guardrails off)" + case !configured: + return "disabled", "no checker configured" + case cfg.Posture >= PostureYolo: + return "advisory", "demoted by posture yolo" + } + specs, _ := effectiveGuardrailSpecs(cfg) + if highestSeverityGuardrailMode(specs) == "advisory" { + return "advisory", "configured advisory" + } + return "enforcing", "" +} + +// reviewerState reports the subagent ask reviewer for the startup line. +func reviewerState(cfg Config) string { + switch { + case cfg.askReviewerDefaultOn: + return "on (default for headless allow-all)" + case cfg.SubagentAskReviewerModel != "" && cfg.Interactive: + return "inert (interactive deployment)" + case cfg.SubagentAskReviewerModel != "": + return "on (configured)" + case cfg.askReviewerOptOut: + return "off (--subagent-ask-reviewer off)" + default: + return "off" + } +} + +// narratePermissionMode is the ONE build-once line reporting the resolved token, +// both halves it set with their lifetimes, and the checker and reviewer states +// as separately scannable items (ADR 0365 AC5.6). The reviewer and the checker +// are different mechanisms and are named separately; neither is described in +// the other's terms. +func narratePermissionMode(cfg Config, checkerConfigured bool) { + mode := cfg.DefaultSessionMode + if mode == "" { + mode = session.ModeDefault + } + checker, checkerReason := checkerState(cfg, checkerConfigured) + attrs := []any{ + "permission_mode", cfg.resolvedPermissionModeName(), + "posture", cfg.Posture.String(), + "posture_scope", "process-wide, fixed at startup; cycling the session mode never changes it", + "session_mode", string(mode), + "session_mode_scope", "default for new sessions; a session may change it", + "guardrails_checker", checker, + "subagent_ask_reviewer", reviewerState(cfg), + } + if checkerReason != "" { + attrs = append(attrs, "guardrails_checker_reason", checkerReason) + } + if checker == "advisory" && cfg.Posture >= PostureYolo { + attrs = append(attrs, "guardrails_checker_note", yoloCheckerAdvisoryNote) + } + cfg.diag().Log(context.Background(), port.LevelInfo, "permission mode", attrs...) + if cfg.Posture == PostureAuto { + cfg.diag().Log(context.Background(), port.LevelInfo, + "permission mode auto: subagents KEEP the command-substitution guard the main agent loses, so a subagent's $(...), backtick, or subshell command that cannot be proved read-only is not auto-run. Headless, the subagent ask reviewer adjudicates it instead of denying it (--subagent-ask-reviewer)") + } +} + +// isAskReviewerOptOut reports the explicit --subagent-ask-reviewer off value, +// mirroring the --guardrails off kill-switch. +func isAskReviewerOptOut(s string) bool { + return strings.EqualFold(strings.TrimSpace(s), "off") +} + +// resolveAskReviewerDefault decides whether the headless subagent ask reviewer +// is on by default (ADR 0365 decision 6): headless (no human approver), an +// allow-all posture, no explicit reviewer model, and no explicit opt-out. It +// resolves its model through the existing ask-reviewer slot with the +// parent-model fallback; when neither resolves, behaviour stays today's +// denial and a WARN names the fix. +func resolveAskReviewerDefault(cfg Config) Config { + if cfg.Interactive || cfg.Posture < PostureAuto || cfg.SubagentAskReviewerModel != "" || cfg.askReviewerOptOut { + return cfg + } + if _, ok := resolveSlotModel(cfg, slotAskReviewer, cfg.Model); !ok && strings.TrimSpace(cfg.Model) == "" { + cfg.diag().Log(context.Background(), port.LevelWarn, + "subagent ask reviewer: the headless allow-all default could not resolve a reviewer model (no ask-reviewer slot and no session model), so a subagent's unresolved permission request is denied as before. Set --subagent-ask-reviewer or bind the ask-reviewer model slot") + return cfg + } + cfg.askReviewerDefaultOn = true + cfg.diag().Log(context.Background(), port.LevelInfo, + "subagent ask reviewer ON by default (headless allow-all): a model may approve a subagent's permission request that nobody else can answer, and each adjudication spends tokens. Configured Deny and Ask rules still win. Opt out with --subagent-ask-reviewer off") + return cfg +} diff --git a/internal/app/posture.go b/internal/app/posture.go index e82c27fdcf..a80314f9d3 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -260,6 +260,9 @@ func foldOperatorPosture(cfg Config) Config { return cfg } cfg.Posture = parsePosture(yamlPosture) + cfg.diag().Log(context.Background(), port.LevelWarn, + "posture: the settings.yaml posture: key is DEPRECATED; use permissionMode: instead (ADR 0365)", + "posture", yamlPosture) return cfg } From 47da52f512dd8766e8eb14b2218657b462f9870a Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:34:49 +0300 Subject: [PATCH 02/48] test(permissions): pin the permission-mode contract in composition Cover ADR 0365 scenarios 1 through 4 plus the startup line and the operator-tier key against the real Build: the token table and its session half, both admission gates with every fix named, the three checker states, the headless reviewer default with its opt-out and degrade path, and that no wire or domain value was added. Point the trust-withheld hints and the model-visible self-knowledge text at --permission-mode, stating that its posture half is process-wide and cycling the session mode never changes it. Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/app/agentdefs.go | 2 +- internal/app/build.go | 13 +- internal/app/jev_router_acceptance_test.go | 35 +- .../app/learned_skills_composition_test.go | 6 +- .../mcp_broker_authorization_vertical_test.go | 17 +- internal/app/mcp_refresh_acceptance_test.go | 4 +- internal/app/multiprovider_e2e_test.go | 9 +- internal/app/pathescape_guardrail_test.go | 2 + internal/app/pathescape_scenario2_test.go | 1 + internal/app/pathescape_scenario3_test.go | 1 + internal/app/permission_mode_test.go | 599 ++++++++++++++++++ internal/app/posture_build_test.go | 63 +- internal/app/project_ingestion_build_test.go | 2 + internal/app/redis_workspace_e2e_test.go | 1 + internal/app/router_test.go | 3 + internal/app/session_debug_acceptance_test.go | 2 +- internal/app/soulselect.go | 2 +- internal/app/steer_composition_test.go | 13 +- internal/app/subagent_agent_router_test.go | 3 + internal/app/subagent_model_default_test.go | 13 +- .../subagent_writable_agent_router_test.go | 1 + internal/app/subprovider_test.go | 9 +- internal/app/team_parallel_router_test.go | 1 + 23 files changed, 716 insertions(+), 86 deletions(-) create mode 100644 internal/app/permission_mode_test.go diff --git a/internal/app/agentdefs.go b/internal/app/agentdefs.go index d482e21095..3a83b28d03 100644 --- a/internal/app/agentdefs.go +++ b/internal/app/agentdefs.go @@ -1546,7 +1546,7 @@ func resolveAgentRegistry(ctx context.Context, cfg Config) *agents.Registry { // (projectIngestionAdmitted). The user-tier + explicit defs stay active // regardless ("ask the human" mode, not "do nothing"). if cfg.AgentsConventional && cfg.Workspace != "" && !projectIngestionAdmitted(cfg) { - cfg.diag().Log(ctx, port.LevelWarn, "agent definitions: project-tier defs WITHHELD (untrusted workspace or project ingestion not granted); user-tier and explicit defs stay active. Pass --trust-project (on a headless root) or run --posture auto on an interactive root to admit its project agent defs", + cfg.diag().Log(ctx, port.LevelWarn, "agent definitions: project-tier defs WITHHELD (untrusted workspace or project ingestion not granted); user-tier and explicit defs stay active. Pass --trust-project (on a headless root) or run --permission-mode auto on an interactive root to admit its project agent defs", "workspace", cfg.Workspace, "dirs", ".mecatl/agents,.claude/agents") } sources := agents.ResolveSources(agents.ResolveOptions{ diff --git a/internal/app/build.go b/internal/app/build.go index 7d33e3f674..45d9fad694 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -4720,7 +4720,7 @@ func resolveRulesSeam(ctx context.Context, cfg Config) prompt.RulesSource { // same gate as agents/skills): untrusted, or the ingestion grant withheld. The // user-tier lanes stay active regardless. if cfg.Workspace != "" && !projectIngestionAdmitted(cfg) { - cfg.diag().Log(ctx, port.LevelWarn, "rules: project-tier rules WITHHELD (untrusted workspace or project ingestion not granted); user-tier rules stay active. Pass --trust-project (on a headless root) or run --posture auto on an interactive root to admit its project rules", + cfg.diag().Log(ctx, port.LevelWarn, "rules: project-tier rules WITHHELD (untrusted workspace or project ingestion not granted); user-tier rules stay active. Pass --trust-project (on a headless root) or run --permission-mode auto on an interactive root to admit its project rules", "workspace", cfg.Workspace, "dirs", ".mecatl/rules,.claude/rules") } sources := rules.ResolveSources(rules.ResolveOptions{ @@ -5102,7 +5102,7 @@ func slashCommandDecision(cfg Config) diagFact { if cfg.Workspace != "" && !projectIngestionAdmitted(cfg) { return diagFact{ level: port.LevelWarn, - msg: "slash commands: project-tier command dirs WITHHELD (untrusted workspace or project ingestion not granted); raw text passes through. Pass --trust-project (on a headless root) or run --posture auto on an interactive root, or pass --commands-dir to enable project slash commands", + msg: "slash commands: project-tier command dirs WITHHELD (untrusted workspace or project ingestion not granted); raw text passes through. Pass --trust-project (on a headless root) or run --permission-mode auto on an interactive root, or pass --commands-dir to enable project slash commands", args: []any{"dirs", ".mecatl/commands,.claude/commands"}, } } @@ -9127,9 +9127,12 @@ const ( "exactly three, one per session, in your as `permission-mode`. `default` resolves each call " + "deny→ask→allow; `plan` denies mutations and expects a plan presented for approval; `acceptEdits` " + "(accept-edits in mecatui) auto-allows Edit and Write only, leaving Shell and every other mutating " + - "tool on the normal rules. mecatui shows the mode in its header, takes `--mode` at launch, and " + - "cycles default → plan → accept-edits on shift+tab. (2) OPERATOR POSTURE: deployment-wide via " + - "--posture, rising strict < trusted < auto < yolo. auto and yolo widen what a call is authorized " + + "tool on the normal rules. mecatui shows the mode in its header, takes a starting mode at launch, and " + + "cycles default → plan → accept-edits on shift+tab. (2) OPERATOR POSTURE: deployment-wide and fixed " + + "at startup, rising strict < trusted < auto < yolo. The operator sets both with one --permission-mode " + + "token (plan, default, accept-edits, trusted, trusted-accept-edits, auto, yolo): its posture half " + + "is process-wide, its mode half is only the default a new session starts in, and cycling the session " + + "mode never changes the posture. auto and yolo widen what a call is authorized " + "to do, not only how much runs without asking: both set an allow-all rule for every tool call. " + "Posture raises project trust on INTERACTIVE roots only: a HEADLESS deployment does NOT trust the " + "checkout by posture alone. Project ingestion and the read-only child shell follow from project " + diff --git a/internal/app/jev_router_acceptance_test.go b/internal/app/jev_router_acceptance_test.go index 26a8afc21d..4270333201 100644 --- a/internal/app/jev_router_acceptance_test.go +++ b/internal/app/jev_router_acceptance_test.go @@ -255,19 +255,20 @@ func TestJEVRouter_Scenario3_CompositionParity(t *testing.T) { srv, calls := jevTestServer(t, "small", 1, 4, 2) provider := &jevBuildProvider{} built, err := buildIsolated(t, t.Context(), Config{ - Workspace: t.TempDir(), - UserModelDir: t.TempDir(), - UseMock: true, - MockProvider: provider, - NoSoul: true, - NoUserModel: true, - NoShell: true, - AllowAllTools: true, - Model: "parent-model", - RouterBackend: "jev", - RouterJevBaseURL: srv.URL, - TypesafeAPIKey: "secret", - ModelAliases: map[string]string{"tiny": "resolved-model"}, + Workspace: t.TempDir(), + UserModelDir: t.TempDir(), + UseMock: true, + MockProvider: provider, + NoSoul: true, + NoUserModel: true, + NoShell: true, + AllowAllTools: true, + GuardrailsDisabled: true, + Model: "parent-model", + RouterBackend: "jev", + RouterJevBaseURL: srv.URL, + TypesafeAPIKey: "secret", + ModelAliases: map[string]string{"tiny": "resolved-model"}, RouterCategories: []permconfig.RouterCategory{ {Name: "small", Description: "small task", Model: "tiny"}, {Name: "large", Description: "large task", Model: "other-model"}, @@ -330,7 +331,7 @@ func TestJEVRouter_Scenario4_BuildConfiguredRequestLimit(t *testing.T) { provider := &jevBuildProvider{} built, err := buildIsolated(t, t.Context(), Config{ Workspace: t.TempDir(), UserModelDir: t.TempDir(), UseMock: true, MockProvider: provider, - NoSoul: true, NoUserModel: true, NoShell: true, AllowAllTools: true, Model: "inherited-model", + NoSoul: true, NoUserModel: true, NoShell: true, AllowAllTools: true, GuardrailsDisabled: true, Model: "inherited-model", RouterBackend: "jev", RouterJevBaseURL: srv.URL, RouterJevMaximumInputBytes: 1, TypesafeAPIKey: "secret", RouterCategories: []permconfig.RouterCategory{ {Name: "small", Description: "small task", Model: "routed-model"}, @@ -366,7 +367,7 @@ func TestJEVRouter_Scenario4_BuildSharedCapacity(t *testing.T) { provider := &jevBuildProvider{parentDelegated: make(chan struct{}, 9)} built, err := buildIsolated(t, t.Context(), Config{ Workspace: t.TempDir(), UserModelDir: t.TempDir(), UseMock: true, MockProvider: provider, - NoSoul: true, NoUserModel: true, NoShell: true, AllowAllTools: true, Model: "parent-model", + NoSoul: true, NoUserModel: true, NoShell: true, AllowAllTools: true, GuardrailsDisabled: true, Model: "parent-model", RouterBackend: "jev", RouterJevBaseURL: srv.URL, TypesafeAPIKey: "secret", RouterCategories: []permconfig.RouterCategory{{Name: "small", Description: "small task", Model: "routed-model"}}, }) @@ -431,7 +432,7 @@ func TestJevLowConfidenceCandidateSurvivesRealDelegation(t *testing.T) { provider := &jevBuildProvider{} built, err := buildIsolated(t, t.Context(), Config{ Workspace: t.TempDir(), UserModelDir: t.TempDir(), UseMock: true, MockProvider: provider, - NoSoul: true, NoUserModel: true, NoShell: true, AllowAllTools: true, Model: "inherited-model", + NoSoul: true, NoUserModel: true, NoShell: true, AllowAllTools: true, GuardrailsDisabled: true, Model: "inherited-model", RouterBackend: "jev", RouterJevModel: "jev-1.13.0", RouterJevBaseURL: srv.URL, RouterJevMinimumConfidence: 0.50, TypesafeAPIKey: "secret", ModelAliases: map[string]string{"candidate-alias": "locally-resolved-candidate"}, @@ -529,7 +530,7 @@ func TestJEVRouter_Scenario2_ExistingRoutingSemantics(t *testing.T) { provider := &jevBuildProvider{subagentArgs: tc.args} cfg := Config{ Workspace: t.TempDir(), UserModelDir: t.TempDir(), UseMock: true, MockProvider: provider, - NoSoul: true, NoShell: true, AllowAllTools: true, Model: "parent-model", + NoSoul: true, NoShell: true, AllowAllTools: true, GuardrailsDisabled: true, Model: "parent-model", } applyJevRouting(&cfg, srv) if tc.agentSetup { diff --git a/internal/app/learned_skills_composition_test.go b/internal/app/learned_skills_composition_test.go index c7bde861b0..647d3bad81 100644 --- a/internal/app/learned_skills_composition_test.go +++ b/internal/app/learned_skills_composition_test.go @@ -25,7 +25,7 @@ func TestBuildOwnerlessSessionHydratesLearnedSkillIntoTool(t *testing.T) { built, err := Build(context.Background(), Config{ Workspace: workspace, Model: "mock", StoreDir: t.TempDir(), UserModelDir: userModelDir, - NoSoul: true, AllowAllTools: true, MockProvider: mockllm.New( + NoSoul: true, AllowAllTools: true, GuardrailsDisabled: true, MockProvider: mockllm.New( mockllm.ToolCallTurn(session.NewToolCall("skill-ownerless", "Skill", []byte(`{"name":"ownerless-recovery"}`))), mockllm.TextTurn("done"), ), @@ -63,7 +63,7 @@ func TestBuildRestartHydratesCallerBoundLearnedSkillIntoListAndTool(t *testing.T config := func(provider *mockllm.Provider) Config { return Config{ Workspace: workspace, Model: "mock", StoreDir: storeDir, UserModelDir: userModelDir, - NoSoul: true, OwnershipEnforced: true, AllowAllTools: true, MockProvider: provider, + NoSoul: true, OwnershipEnforced: true, AllowAllTools: true, GuardrailsDisabled: true, MockProvider: provider, } } built1, err := Build(context.Background(), config(mockllm.New(mockllm.TextTurn("created")))) @@ -131,7 +131,7 @@ func TestReplicaHydrationConvergesAcrossReplacementAndRollback(t *testing.T) { ) replicaB, err := Build(context.Background(), Config{ Workspace: workspace, Model: "mock", StoreDir: storeDir, UserModelDir: userModelDir, - NoSoul: true, Headless: true, OwnershipEnforced: true, AllowAllTools: true, MockProvider: provider, + NoSoul: true, Headless: true, OwnershipEnforced: true, AllowAllTools: true, GuardrailsDisabled: true, MockProvider: provider, }) if err != nil { t.Fatal(err) diff --git a/internal/app/mcp_broker_authorization_vertical_test.go b/internal/app/mcp_broker_authorization_vertical_test.go index 38c5eba715..dd38cf2ba1 100644 --- a/internal/app/mcp_broker_authorization_vertical_test.go +++ b/internal/app/mcp_broker_authorization_vertical_test.go @@ -83,14 +83,15 @@ func TestSessionMCPAuthorization_GrantRegressionParksAndResumes(t *testing.T) { }) fixture.mcpClient = fixture.clientWithRoots(roots) built, err := app.Build(ctx, app.Config{ - Workspace: t.TempDir(), - UserModelDir: t.TempDir(), - StoreDir: t.TempDir(), - MockProvider: provider, - NoSoul: true, - AllowAllTools: true, - OwnershipEnforced: true, - MCPAuthority: declaration, + Workspace: t.TempDir(), + UserModelDir: t.TempDir(), + StoreDir: t.TempDir(), + MockProvider: provider, + NoSoul: true, + AllowAllTools: true, + GuardrailsDisabled: true, + OwnershipEnforced: true, + MCPAuthority: declaration, MCPBrokerDiscovered: []mcpbroker.ToolDefinition{{ Backend: "github", Name: toolName, Description: "read protected data", Schema: json.RawMessage(`{"type":"object"}`), ReadOnly: true, }}, diff --git a/internal/app/mcp_refresh_acceptance_test.go b/internal/app/mcp_refresh_acceptance_test.go index 4e50be3dfd..3d08246039 100644 --- a/internal/app/mcp_refresh_acceptance_test.go +++ b/internal/app/mcp_refresh_acceptance_test.go @@ -62,7 +62,9 @@ func TestMCPSourceReconciliation_Scenario4_RealBuildPublicationAndExplicitGrant( defer flaky.Close() built, err := buildIsolated(t, ctx, Config{ Workspace: workspace, StoreDir: storeDir, MockProvider: provider, NoSoul: true, - MCPServers: []mcp.ServerConfig{{Name: "live", URL: newMCPTestServer(t)}, {Name: "flaky", URL: flaky.URL}}, + AllowAllTools: true, + GuardrailsDisabled: true, + MCPServers: []mcp.ServerConfig{{Name: "live", URL: newMCPTestServer(t)}, {Name: "flaky", URL: flaky.URL}}, }) if err != nil { t.Fatalf("Build with published MCP runtime: %v", err) diff --git a/internal/app/multiprovider_e2e_test.go b/internal/app/multiprovider_e2e_test.go index 9e3544fe06..799b794e2f 100644 --- a/internal/app/multiprovider_e2e_test.go +++ b/internal/app/multiprovider_e2e_test.go @@ -541,10 +541,11 @@ func TestSubAgentPinsAnthropic(t *testing.T) { } built, err := buildIsolated(t, ctx, Config{ - Workspace: workspace, - NoSoul: true, - AgentsDirs: []string{agentsDir}, - AllowAllTools: true, // --yolo: auto-approve the routed Subagent + Workspace: workspace, + NoSoul: true, + AgentsDirs: []string{agentsDir}, + AllowAllTools: true, // --yolo: auto-approve the routed Subagent + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{ "OPENAI_API_KEY": "sk-x", "ANTHROPIC_API_KEY": "sk-x", diff --git a/internal/app/pathescape_guardrail_test.go b/internal/app/pathescape_guardrail_test.go index 16677a43d2..a5e06b2a01 100644 --- a/internal/app/pathescape_guardrail_test.go +++ b/internal/app/pathescape_guardrail_test.go @@ -177,6 +177,7 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { } bcfg := escapeCfg(t, f, PostureAuto, turns...) bcfg.GuardrailsModel = "checker-model" + bcfg.GuardrailsDisabled = false // escapeCfg declares off; this test configures a checker instead bcfg.GuardrailsEscape = true built, err := buildIsolated(t, context.Background(), bcfg) if err != nil { @@ -202,6 +203,7 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { f := setupEscapeFS(t) bcfg := escapeCfg(t, f, PostureAuto, readEscapeTurns(f.target)...) bcfg.GuardrailsModel = "checker-model" + bcfg.GuardrailsDisabled = false // escapeCfg declares off; this test configures a checker instead // Isolate the escape-route assertion from the contextual guardrails' default inbound Read // coverage: an explicit unrelated rule keeps guardrails enabled without // reviewing this Read result through the ordinary tool boundary. diff --git a/internal/app/pathescape_scenario2_test.go b/internal/app/pathescape_scenario2_test.go index f343addfc3..b5d2d0c09f 100644 --- a/internal/app/pathescape_scenario2_test.go +++ b/internal/app/pathescape_scenario2_test.go @@ -65,6 +65,7 @@ func escapeCfg(t *testing.T, f escapeFixture, posture Posture, turns ...mockllm. Workspace: f.workspace, NoSoul: true, Posture: posture, + GuardrailsDisabled: true, PostureFlagSet: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-openai"}), liveModelHTTPClient: offlineHTTPClient(), diff --git a/internal/app/pathescape_scenario3_test.go b/internal/app/pathescape_scenario3_test.go index cccdf00ff1..4a13d80e21 100644 --- a/internal/app/pathescape_scenario3_test.go +++ b/internal/app/pathescape_scenario3_test.go @@ -69,6 +69,7 @@ func writeEscapeCfg(t *testing.T, f writeFixture, posture Posture, turns ...mock Workspace: f.workspace, NoSoul: true, Posture: posture, + GuardrailsDisabled: true, PostureFlagSet: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-openai"}), liveModelHTTPClient: offlineHTTPClient(), diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go new file mode 100644 index 0000000000..60e7017f83 --- /dev/null +++ b/internal/app/permission_mode_test.go @@ -0,0 +1,599 @@ +package app + +import ( + "context" + "os" + "path/filepath" + "slices" + "strings" + "testing" + + mecatlv1 "github.com/stacklok/mecatl/contracts/gen/go/mecatl/v1" + "github.com/stacklok/mecatl/engine/adapter/memfs" + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/permconfig" +) + +// permissionModeCfg is the offline Build fixture for the ADR 0365 tests: an +// explicit --permission-mode token over the mock provider. +func permissionModeCfg(t *testing.T, token string, diag port.Diagnostics) Config { + t.Helper() + return Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + PermissionMode: token, + PermissionModeFlagSet: true, + Diagnostics: diag, + } +} + +// builtDefaultSessionMode reports the mode a CreateSession that leaves mode +// unspecified starts in: the session half of the token. +func builtDefaultSessionMode(t *testing.T, built *Built) session.PermissionMode { + t.Helper() + sess, err := built.Service.CreateSession(context.Background(), "", defaultLimits()) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + return sess.Mode +} + +func TestADR_0365_TokenTableResolvesExactPairs(t *testing.T) { + want := map[string]struct { + posture Posture + mode session.PermissionMode + }{ + "plan": {PostureStrict, session.ModePlan}, + "default": {PostureStrict, session.ModeDefault}, + "accept-edits": {PostureStrict, session.ModeAccept}, + "trusted": {PostureTrusted, session.ModeDefault}, + "trusted-accept-edits": {PostureTrusted, session.ModeAccept}, + "auto": {PostureAuto, session.ModeDefault}, + "yolo": {PostureYolo, session.ModeDefault}, + } + if got := PermissionModeNames(); len(got) != len(want) { + t.Fatalf("token set = %v, want exactly the %d ADR tokens", got, len(want)) + } + for name, pair := range want { + tok, err := ParsePermissionMode(name) + if err != nil { + t.Fatalf("ParsePermissionMode(%q): %v", name, err) + } + if tok.Posture != pair.posture || tok.SessionMode != pair.mode { + t.Errorf("%s resolves to (%s, %s), want (%s, %s)", name, tok.Posture, tok.SessionMode, pair.posture, pair.mode) + } + + // Through the real Build: the posture echo and the session default. + cfg := permissionModeCfg(t, name, port.NopDiagnostics{}) + cfg.GuardrailsDisabled = pair.posture >= PostureAuto + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build %s: %v", name, err) + } + if got := postureEchoFromBuild(t, built); got != pair.posture.String() { + t.Errorf("%s: echoed posture %q, want %q", name, got, pair.posture) + } + if got := builtDefaultSessionMode(t, built); got != pair.mode { + t.Errorf("%s: unspecified-mode session started in %q, want %q", name, got, pair.mode) + } + built.Close() + } + + _, err := ParsePermissionMode("autonomous") + if err == nil { + t.Fatal("an unknown token must be an error") + } + for _, name := range PermissionModeNames() { + if !strings.Contains(err.Error(), name) { + t.Errorf("unknown-token error must name the valid set; missing %q in %v", name, err) + } + } + if _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "autonomous", port.NopDiagnostics{})); err == nil || !strings.Contains(err.Error(), "trusted-accept-edits") { + t.Fatalf("Build with an unknown token must fail naming the valid set; got %v", err) + } +} + +func TestADR_0365_TrustedKeepsCurrentMeaning(t *testing.T) { + cfg := permissionModeCfg(t, "trusted", port.NopDiagnostics{}) + legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, Posture: PostureTrusted, PostureFlagSet: true} + for name, c := range map[string]Config{"token": cfg, "--posture trusted": legacy} { + built, err := buildIsolated(t, context.Background(), c) + if err != nil { + t.Fatalf("%s: Build: %v", name, err) + } + if got := postureEchoFromBuild(t, built); got != "trusted" { + t.Errorf("%s: posture %q, want trusted", name, got) + } + if got := builtDefaultSessionMode(t, built); got != session.ModeDefault { + t.Errorf("%s: session mode %q, want default", name, got) + } + built.Close() + } +} + +func TestADR_0365_TrustedAcceptEditsIsNameable(t *testing.T) { + built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", port.NopDiagnostics{})) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + if got := postureEchoFromBuild(t, built); got != "trusted" { + t.Errorf("posture %q, want trusted", got) + } + if got := builtDefaultSessionMode(t, built); got != session.ModeAccept { + t.Errorf("session mode %q, want acceptEdits", got) + } +} + +func TestADR_0365_AllowAllTokenRequiresChecker(t *testing.T) { + for _, token := range []string{"auto", "yolo"} { + _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) + if err == nil { + t.Fatalf("%s with no checker and no kill-switch must refuse to start", token) + } + // The deprecated surface reaches the same resolved posture and the same gate. + legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, AllowAllTools: true} + if _, err := buildIsolated(t, context.Background(), legacy); err == nil { + t.Fatal("--yolo with no checker must refuse to start too: the gate keys on the resolved posture") + } + // Either declared choice satisfies it. + off := permissionModeCfg(t, token, port.NopDiagnostics{}) + off.GuardrailsDisabled = true + built, err := buildIsolated(t, context.Background(), off) + if err != nil { + t.Fatalf("%s with --guardrails off must start: %v", token, err) + } + built.Close() + checked := permissionModeCfg(t, token, port.NopDiagnostics{}) + checked.GuardrailsModel = "mock-checker" + built, err = buildIsolated(t, context.Background(), checked) + if err != nil { + t.Fatalf("%s with a configured checker must start: %v", token, err) + } + built.Close() + } +} + +func TestADR_0365_CheckerRefusalNamesEveryFix(t *testing.T) { + _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "auto", port.NopDiagnostics{})) + if err == nil { + t.Fatal("auto with no checker must refuse") + } + for _, want := range []string{`"auto"`, "--guardrails-model", "`guardrail` model slot", "--guardrails off"} { + if !strings.Contains(err.Error(), want) { + t.Errorf("refusal must name %q; got: %v", want, err) + } + } +} + +func TestADR_0365_GateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { + properties := []string{"pre-tool veto", "approve-once human ask", "fail-closed"} + + _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "yolo", port.NopDiagnostics{})) + if err == nil { + t.Fatal("yolo with no checker must refuse") + } + for _, p := range properties { + if !strings.Contains(err.Error(), p) { + t.Errorf("yolo refusal must name %q as a property the checker lacks; got: %v", p, err) + } + } + + rec := slogdiagBuffer(t) + cfg := permissionModeCfg(t, "yolo", rec.diag) + cfg.GuardrailsModel = "mock-checker" + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + line := rec.lineContaining(`msg="permission mode"`) + if !strings.Contains(line, "guardrails_checker=advisory") { + t.Fatalf("yolo startup line must report the checker as advisory; line: %q", line) + } + for _, p := range properties { + if !strings.Contains(line, p) { + t.Errorf("yolo startup line must name %q; line: %q", p, line) + } + } +} + +func TestADR_0365_NonAllowAllTokensRequireNoChecker(t *testing.T) { + for _, token := range []string{"plan", "default", "accept-edits", "trusted", "trusted-accept-edits"} { + built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) + if err != nil { + t.Fatalf("%s must start with no checker: %v", token, err) + } + built.Close() + } +} + +func TestADR_0365_StartupLineNamesCheckerState(t *testing.T) { + cases := []struct { + name string + cfg Config + want string + }{ + {"enforcing", Config{Posture: PostureAuto, GuardrailsModel: "m"}, "enforcing"}, + {"advisory at yolo", Config{Posture: PostureYolo, GuardrailsModel: "m"}, "advisory"}, + {"kill-switch", Config{Posture: PostureAuto, GuardrailsDisabled: true}, "disabled"}, + {"none at strict", Config{}, "disabled"}, + } + for _, tc := range cases { + configured := tc.cfg.GuardrailsModel != "" + if got, _ := checkerState(tc.cfg, configured); got != tc.want { + t.Errorf("%s: checker state %q, want %q", tc.name, got, tc.want) + } + } + + rec := slogdiagBuffer(t) + cfg := permissionModeCfg(t, "auto", rec.diag) + cfg.GuardrailsModel = "mock-checker" + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + if line := rec.lineContaining(`msg="permission mode"`); !strings.Contains(line, "guardrails_checker=enforcing") { + t.Fatalf("an auto deployment with a checker must report it enforcing; line: %q", line) + } +} + +// headlessCfg is a headless root with no trust source. +func headlessCfg(t *testing.T, token string, diag port.Diagnostics) Config { + t.Helper() + withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) + cfg := permissionModeCfg(t, token, diag) + cfg.Headless = true + return cfg +} + +func TestADR_0365_HeadlessTrustTokenRefused(t *testing.T) { + for _, token := range []string{"trusted", "trusted-accept-edits"} { + _, err := buildIsolated(t, context.Background(), headlessCfg(t, token, port.NopDiagnostics{})) + if err == nil { + t.Fatalf("%s on a headless root with no trust source must refuse", token) + } + for _, want := range []string{"--trust-project", "trustedWorkspaces", "default or auto"} { + if !strings.Contains(err.Error(), want) { + t.Errorf("%s refusal must name %q; got: %v", token, want, err) + } + } + } +} + +func TestADR_0365_HeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { + t.Run("explicit --trust-project", func(t *testing.T) { + cfg := headlessCfg(t, "trusted", port.NopDiagnostics{}) + cfg.TrustProject = true + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("explicit trust must satisfy the gate: %v", err) + } + built.Close() + }) + t.Run("declared trustedWorkspaces", func(t *testing.T) { + ws := t.TempDir() + withTrustEnv(t, trustSettingsEnv(t.TempDir(), []byte("trustedWorkspaces:\n - "+ws+"\n"))) + cfg := permissionModeCfg(t, "trusted-accept-edits", port.NopDiagnostics{}) + cfg.Headless = true + cfg.Workspace = ws + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("declared trust must satisfy the gate, because it runs after the trust fold: %v", err) + } + built.Close() + }) +} + +func TestADR_0365_HeadlessAllowAllStartsWithoutTrust(t *testing.T) { + for _, token := range []string{"auto", "yolo"} { + rec := slogdiagBuffer(t) + cfg := headlessCfg(t, token, rec.diag) + cfg.GuardrailsDisabled = true + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("%s on a headless root must start: %v", token, err) + } + built.Close() + if line := rec.lineContaining(`msg="operator posture"`); !strings.Contains(line, "project_ingestion=false") { + t.Errorf("%s: headless without trust must admit no project ingestion; line: %q", token, line) + } + if !strings.Contains(rec.String(), "project trust WITHHELD") { + t.Errorf("%s: headless allow-all without trust must WARN naming the withheld trust; log:\n%s", token, rec.String()) + } + } +} + +func TestADR_0365_InteractiveTrustTokenGrantsTrust(t *testing.T) { + withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) + rec := slogdiagBuffer(t) + built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted", rec.diag)) + if err != nil { + t.Fatalf("interactive trusted must start: %v", err) + } + defer built.Close() + if line := rec.lineContaining(`msg="operator posture"`); !strings.Contains(line, "trust_project=true") { + t.Errorf("interactive trusted must grant project trust; line: %q", line) + } + if strings.Contains(rec.String(), "WITHHELD") { + t.Errorf("interactive trusted must not WARN about withheld trust; log:\n%s", rec.String()) + } +} + +func TestADR_0365_AllowAllNarratesSubagentAsymmetry(t *testing.T) { + rec := slogdiagBuffer(t) + cfg := permissionModeCfg(t, "auto", rec.diag) + cfg.GuardrailsDisabled = true + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + built.Close() + line := rec.lineContaining("KEEP the command-substitution guard") + if line == "" || !strings.Contains(line, "--subagent-ask-reviewer") { + t.Fatalf("auto must narrate the subagent asymmetry and name the reviewer; log:\n%s", rec.String()) + } +} + +// headlessAllowAll is a headless auto deployment with the checker declared off. +func headlessAllowAll(t *testing.T, diag port.Diagnostics) Config { + t.Helper() + cfg := headlessCfg(t, "auto", diag) + cfg.GuardrailsDisabled = true + return cfg +} + +func TestADR_0365_HeadlessAllowAllDefaultsReviewerOn(t *testing.T) { + rec := slogdiagBuffer(t) + built, err := buildIsolated(t, context.Background(), headlessAllowAll(t, rec.diag)) + if err != nil { + t.Fatalf("Build: %v", err) + } + built.Close() + if !strings.Contains(rec.String(), "subagent ask reviewer ON by default") { + t.Fatalf("headless allow-all must engage the reviewer by default; log:\n%s", rec.String()) + } + + // The model resolves through the existing slot, then the parent model. + cfg := Config{Posture: PostureAuto, Model: "parent-model", Diagnostics: port.NopDiagnostics{}} + cfg = resolveAskReviewerDefault(cfg) + if !cfg.askReviewerDefaultOn { + t.Fatal("resolveAskReviewerDefault must engage the reviewer") + } + deps, ok := askAdjudicatorDeps(cfg, nil, nil, "", "parent-model") + if !ok || deps.Model != "parent-model" { + t.Fatalf("default reviewer must fall back to the parent model; ok=%t model=%q", ok, deps.Model) + } + cfg.ModelSlots = map[string]string{slotAskReviewer: "reviewer-model"} + deps, ok = askAdjudicatorDeps(cfg, nil, nil, "", "parent-model") + if !ok || deps.Model != "reviewer-model" { + t.Fatalf("default reviewer must resolve through the ask-reviewer slot; ok=%t model=%q", ok, deps.Model) + } +} + +func TestADR_0365_ReviewerDefaultIsOptOutAndNarrated(t *testing.T) { + rec := slogdiagBuffer(t) + built, err := buildIsolated(t, context.Background(), headlessAllowAll(t, rec.diag)) + if err != nil { + t.Fatalf("Build: %v", err) + } + built.Close() + on := rec.lineContaining("subagent ask reviewer ON by default") + for _, want := range []string{"a model may approve", "spends tokens", "--subagent-ask-reviewer off"} { + if !strings.Contains(on, want) { + t.Errorf("default-on narration must say %q; line: %q", want, on) + } + } + + rec = slogdiagBuffer(t) + cfg := headlessAllowAll(t, rec.diag) + cfg.SubagentAskReviewerModel = "off" + built, err = buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build with --subagent-ask-reviewer off: %v", err) + } + built.Close() + if strings.Contains(rec.String(), "ON by default") { + t.Fatalf("the opt-out must restore today's behaviour; log:\n%s", rec.String()) + } + if line := rec.lineContaining(`msg="permission mode"`); !strings.Contains(line, "off (--subagent-ask-reviewer off)") { + t.Fatalf("the startup line must state the opt-out is in effect; line: %q", line) + } +} + +func TestADR_0365_ReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { + rec := slogdiagBuffer(t) + cfg := resolveAskReviewerDefault(Config{Posture: PostureAuto, Diagnostics: rec.diag}) + if cfg.askReviewerDefaultOn { + t.Fatal("with no resolvable reviewer model the default must stay off") + } + if _, ok := askAdjudicatorDeps(cfg, nil, nil, "", ""); ok { + t.Fatal("no reviewer must be built, so behaviour is today's denial") + } + if !strings.Contains(rec.String(), "--subagent-ask-reviewer ") { + t.Fatalf("a WARN must name the fix; log:\n%s", rec.String()) + } +} + +func TestADR_0365_ReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { + for name, cfg := range map[string]Config{ + "interactive auto": {Posture: PostureAuto, Interactive: true, Model: "m"}, + "headless strict": {Posture: PostureStrict, Model: "m"}, + "headless trusted": {Posture: PostureTrusted, Model: "m"}, + } { + cfg.Diagnostics = port.NopDiagnostics{} + if resolveAskReviewerDefault(cfg).askReviewerDefaultOn { + t.Errorf("%s must not engage the reviewer default", name) + } + } +} + +func TestADR_0365_ReviewerAndCheckerNarratedSeparately(t *testing.T) { + rec := slogdiagBuffer(t) + cfg := headlessCfg(t, "auto", rec.diag) + cfg.GuardrailsModel = "mock-checker" + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + built.Close() + line := rec.lineContaining(`msg="permission mode"`) + if !strings.Contains(line, "guardrails_checker=") || !strings.Contains(line, "subagent_ask_reviewer=") { + t.Fatalf("the startup line must carry the checker and the reviewer as separate items; line: %q", line) + } + on := strings.ToLower(rec.lineContaining("subagent ask reviewer ON by default")) + if strings.Contains(on, "guardrail") || strings.Contains(on, "checker") { + t.Errorf("the reviewer narration must not describe itself in the checker's terms; line: %q", on) + } + for _, s := range []string{"enforcing", "advisory", "disabled"} { + if strings.Contains(s, "review") { + t.Errorf("checker state %q must not describe itself in the reviewer's terms", s) + } + } +} + +func TestADR_0365_StartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing.T) { + rec := slogdiagBuffer(t) + built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", rec.diag)) + if err != nil { + t.Fatalf("Build: %v", err) + } + built.Close() + line := rec.lineContaining(`msg="permission mode"`) + for _, want := range []string{ + "permission_mode=trusted-accept-edits", + "posture=trusted", + "session_mode=acceptEdits", + "process-wide", + "a session may change it", + "guardrails_checker=disabled", + "subagent_ask_reviewer=off", + } { + if !strings.Contains(line, want) { + t.Errorf("startup line must carry %q; line: %q", want, line) + } + } + if n := strings.Count(rec.String(), `msg="permission mode"`); n != 1 { + t.Errorf("the permission-mode line must be emitted exactly once per Build, got %d", n) + } +} + +func TestADR_0365_PermissionModeIsOperatorTierOnly(t *testing.T) { + operatorFile := func(t *testing.T, token string) string { + t.Helper() + path := filepath.Join(t.TempDir(), "operator.yaml") + if err := os.WriteFile(path, []byte("permissionMode: "+token+"\n"), 0o600); err != nil { + t.Fatal(err) + } + return path + } + base := func(t *testing.T) Config { + return Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, Diagnostics: port.NopDiagnostics{}} + } + + t.Run("CLI tier honoured", func(t *testing.T) { + cfg := base(t) + cfg.PermissionConfigs = []string{operatorFile(t, "trusted-accept-edits")} + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + if got := postureEchoFromBuild(t, built); got != "trusted" { + t.Errorf("posture %q, want trusted", got) + } + if got := builtDefaultSessionMode(t, built); got != session.ModeAccept { + t.Errorf("session mode %q, want acceptEdits", got) + } + }) + t.Run("user-global tier honoured", func(t *testing.T) { + env := trustSettingsEnv(t.TempDir(), []byte("permissionMode: plan\n")) + withTrustEnv(t, env) + cfg := base(t) + cfg.PermissionsConventional = true + cfg.permConfigEnv = &env + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + if got := builtDefaultSessionMode(t, built); got != session.ModePlan { + t.Errorf("session mode %q, want plan", got) + } + }) + t.Run("explicit flag outranks the key", func(t *testing.T) { + cfg := permissionModeCfg(t, "plan", port.NopDiagnostics{}) + cfg.PermissionConfigs = []string{operatorFile(t, "trusted")} + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + if got := postureEchoFromBuild(t, built); got != "strict" { + t.Errorf("posture %q, want strict from the flag", got) + } + if got := builtDefaultSessionMode(t, built); got != session.ModePlan { + t.Errorf("session mode %q, want plan from the flag", got) + } + }) + t.Run("project tier ignored with a WARN", func(t *testing.T) { + // Composed: a trusted workspace's project permissionMode: never becomes the + // mode; only --trust-project's own trusted posture applies. + cfg := base(t) + cfg.TrustProject = true + mkdirProjectSettings(t, cfg.Workspace, "permissionMode: yolo\n") + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + if got := postureEchoFromBuild(t, built); got != "trusted" { + t.Errorf("a project-tier permissionMode must be ignored; posture %q", got) + } + // The WARN fires where the project file is read: the resolver's lazy + // per-root Resolve. + isolateUserConfig(t) + rec := slogdiagBuffer(t) + ws := memfs.NewWorkspace("/repo") + if err := ws.Write(context.Background(), ".mecatl/settings.yaml", []byte("permissionMode: yolo\n")); err != nil { + t.Fatal(err) + } + res := permconfig.New(permconfig.Options{Conventional: true, TrustProject: true, Diagnostics: rec.diag}) + _ = res.Resolve(context.Background(), ws) + if got := res.OperatorPermissionMode(); got != "" { + t.Errorf("a project-tier permissionMode must not become the operator value; got %q", got) + } + if !strings.Contains(rec.String(), "IGNORING a project-tier permissionMode") { + t.Errorf("a project-tier permissionMode must WARN; log:\n%s", rec.String()) + } + }) +} + +// TestInvariant_NoWireOrDomainSurfaceChanged pins that the vocabulary added no +// session-selectable value (ADR 0365 decision 3): the domain keeps its three +// modes with their strings, the proto enum keeps its four values, and an old +// snapshot's mode string still round-trips. `task api:check` covers the engine +// API surface itself. +func TestInvariant_NoWireOrDomainSurfaceChanged(t *testing.T) { + if got := []session.PermissionMode{session.ModeDefault, session.ModePlan, session.ModeAccept}; !slices.Equal(got, []session.PermissionMode{"default", "plan", "acceptEdits"}) { + t.Fatalf("session modes changed: %v", got) + } + names := make([]string, 0, len(mecatlv1.PermissionMode_value)) + for name := range mecatlv1.PermissionMode_value { + names = append(names, name) + } + slices.Sort(names) + want := []string{"PERMISSION_MODE_ACCEPT_EDITS", "PERMISSION_MODE_DEFAULT", "PERMISSION_MODE_PLAN", "PERMISSION_MODE_UNSPECIFIED"} + if !slices.Equal(names, want) { + t.Fatalf("proto PermissionMode values = %v, want %v", names, want) + } + for _, tok := range permissionModeTable { + if !slices.Contains([]session.PermissionMode{session.ModeDefault, session.ModePlan, session.ModeAccept}, tok.SessionMode) { + t.Errorf("token %s writes a session mode outside the domain's three: %q", tok.Name, tok.SessionMode) + } + } +} diff --git a/internal/app/posture_build_test.go b/internal/app/posture_build_test.go index 3b151d6119..12ec1b02b1 100644 --- a/internal/app/posture_build_test.go +++ b/internal/app/posture_build_test.go @@ -47,12 +47,13 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { t.Run("operator auto flows to composed posture", func(t *testing.T) { diag := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, - Diagnostics: diag.diag, + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, + GuardrailsDisabled: true, + Diagnostics: diag.diag, }) if err != nil { t.Fatalf("Build: %v", err) @@ -82,6 +83,7 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { NoSoul: true, PermissionsConventional: true, permConfigEnv: &env, + GuardrailsDisabled: true, Diagnostics: port.NopDiagnostics{}, }) if err != nil { @@ -98,14 +100,15 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { t.Run("operator auto headless withholds ingestion (fail-safe)", func(t *testing.T) { diag := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - Headless: true, - Shell: "/bin/sh", // a configured shell so the UNTRUSTED cause (not the empty-shell cause) is operative for the shell-DISABLED fact - PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, - Diagnostics: diag.diag, + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: true, + Shell: "/bin/sh", // a configured shell so the UNTRUSTED cause (not the empty-shell cause) is operative for the shell-DISABLED fact + PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, + GuardrailsDisabled: true, + Diagnostics: diag.diag, }) if err != nil { t.Fatalf("Build: %v", err) @@ -141,14 +144,15 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { t.Run("operator auto interactive grants ingestion (dev default)", func(t *testing.T) { diag := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - Headless: false, - Shell: "/bin/sh", // a configured shell so the untrusted-shell-DISABLED fact would fire if the gate tripped (it must NOT here) - PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, - Diagnostics: diag.diag, + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: false, + Shell: "/bin/sh", // a configured shell so the untrusted-shell-DISABLED fact would fire if the gate tripped (it must NOT here) + PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, + GuardrailsDisabled: true, + Diagnostics: diag.diag, }) if err != nil { t.Fatalf("Build: %v", err) @@ -206,13 +210,14 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { t.Run("operator yolo on a privileged Config is refused", func(t *testing.T) { built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - PermissionConfigs: []string{writeOperatorPostureFile(t, "yolo")}, - Privileged: true, // root && !sandbox, as the cmd would compute - Diagnostics: port.NopDiagnostics{}, + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + PermissionConfigs: []string{writeOperatorPostureFile(t, "yolo")}, + GuardrailsDisabled: true, + Privileged: true, // root && !sandbox, as the cmd would compute + Diagnostics: port.NopDiagnostics{}, }) if err == nil { built.Close() diff --git a/internal/app/project_ingestion_build_test.go b/internal/app/project_ingestion_build_test.go index f9ed11c0d3..7b9a1cf69b 100644 --- a/internal/app/project_ingestion_build_test.go +++ b/internal/app/project_ingestion_build_test.go @@ -40,6 +40,7 @@ func TestHeadlessAutoWithoutTrustProjectSuppressesProjectAgentDefs(t *testing.T) NoSoul: true, AgentsConventional: true, Posture: PostureAuto, + GuardrailsDisabled: true, Headless: true, // a headless root does NOT grant ingestion via the ladder // TrustProject stays FALSE — the operator did not pass --trust-project. Diagnostics: diag.diag, @@ -69,6 +70,7 @@ func TestHeadlessAutoWithoutTrustProjectSuppressesProjectAgentDefs(t *testing.T) NoSoul: true, AgentsConventional: true, Posture: PostureAuto, + GuardrailsDisabled: true, Headless: true, TrustProject: true, // the explicit opt-in admits ingestion on the headless root Diagnostics: nil, // port.NopDiagnostics via nil diff --git a/internal/app/redis_workspace_e2e_test.go b/internal/app/redis_workspace_e2e_test.go index 2cab10912a..fb0961ba81 100644 --- a/internal/app/redis_workspace_e2e_test.go +++ b/internal/app/redis_workspace_e2e_test.go @@ -234,6 +234,7 @@ func TestRedisWorkspaceExternalLookingListDirNeverFallsBackToHost(t *testing.T) MockProvider: provider, NoSoul: true, Posture: PostureYolo, + GuardrailsDisabled: true, PostureFlagSet: true, }) if err != nil { diff --git a/internal/app/router_test.go b/internal/app/router_test.go index 6318ab715b..92f5dbbd25 100644 --- a/internal/app/router_test.go +++ b/internal/app/router_test.go @@ -460,6 +460,7 @@ func TestRouterRoutesChildToClassifiedModelE2E(t *testing.T) { }, RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { @@ -522,6 +523,7 @@ func TestRouterOffIsByteIdenticalE2E(t *testing.T) { Model: "gpt-5", // OFF: no taxonomy ⇒ byte-identical to no router (no classifier call). AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { @@ -612,6 +614,7 @@ func TestRouterCategorySelectorEmptyReasonReducesOnWireE2E(t *testing.T) { }, RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { diff --git a/internal/app/session_debug_acceptance_test.go b/internal/app/session_debug_acceptance_test.go index ac994fbc6f..990ebec604 100644 --- a/internal/app/session_debug_acceptance_test.go +++ b/internal/app/session_debug_acceptance_test.go @@ -243,7 +243,7 @@ func TestSessionDebuggerCrossBoundaryAcceptance(t *testing.T) { ), mockllm.TextTurn("diagnosis and issue draft ready"), ) - built2, err := buildIsolated(t, ctx, Config{Workspace: workspace, StoreDir: storeDir, NoSoul: true, MockProvider: debugProvider, MCPServers: []mcp.ServerConfig{{Name: "github", URL: mcpURL}}, Posture: PostureYolo, PostureFlagSet: true, Interactive: true}) + built2, err := buildIsolated(t, ctx, Config{Workspace: workspace, StoreDir: storeDir, NoSoul: true, MockProvider: debugProvider, MCPServers: []mcp.ServerConfig{{Name: "github", URL: mcpURL}}, Posture: PostureYolo, PostureFlagSet: true, GuardrailsDisabled: true, Interactive: true}) if err != nil { t.Fatalf("restart Build: %v", err) } diff --git a/internal/app/soulselect.go b/internal/app/soulselect.go index 07b26a1487..0d7d7c5a43 100644 --- a/internal/app/soulselect.go +++ b/internal/app/soulselect.go @@ -303,7 +303,7 @@ func selectSoulSource(cfg Config, io baselineIO, gate soulGate) (prompt.SoulSour // trusted AND the ingestion grant (projectIngestionAdmitted). A not-admitted // project soul is dropped silently-but-LOGGED (Warn), never an error. if !projectIngestionAdmitted(cfg) { - cfg.diag().Log(context.Background(), port.LevelWarn, "soul: a project-sourced soul was discovered but is NOT INGESTED (untrusted workspace or project ingestion not granted); dropping it (no fragment). Pass --trust-project (on a headless root) or run --posture auto on an interactive root to honour a soul discovered in this repo (only for a repo you trust)", + cfg.diag().Log(context.Background(), port.LevelWarn, "soul: a project-sourced soul was discovered but is NOT INGESTED (untrusted workspace or project ingestion not granted); dropping it (no fragment). Pass --trust-project (on a headless root) or run --permission-mode auto on an interactive root to honour a soul discovered in this repo (only for a repo you trust)", "path", projectPath) return nil, soulMeta{Provenance: soulProject, Trusted: false, SHA256: projRes.SHA256, Size: projRes.Size} } diff --git a/internal/app/steer_composition_test.go b/internal/app/steer_composition_test.go index 56f6860a2a..cb29fc28ce 100644 --- a/internal/app/steer_composition_test.go +++ b/internal/app/steer_composition_test.go @@ -97,12 +97,13 @@ func TestSteer_EnabledByDefaultEndToEnd(t *testing.T) { // dispatch auto-approves (Interactive is false; an ask would park the run // headless instead of holding it mid-dispatch the way this test needs). built, err := buildIsolated(t, ctx, Config{ - Workspace: t.TempDir(), - Model: "mock", - NoSoul: true, - MockProvider: llm, - AllowAllTools: true, - extraCoreTools: []tool.Tool{block}, + Workspace: t.TempDir(), + Model: "mock", + NoSoul: true, + MockProvider: llm, + AllowAllTools: true, + GuardrailsDisabled: true, + extraCoreTools: []tool.Tool{block}, extraCoreToolClassifications: map[string]server.ClassificationEntry{ "SteerBlock": {Kind: server.KindDerived, Rationale: "test tool is contained within the current authorized run"}, }, diff --git a/internal/app/subagent_agent_router_test.go b/internal/app/subagent_agent_router_test.go index 2088d84c4f..08921751a8 100644 --- a/internal/app/subagent_agent_router_test.go +++ b/internal/app/subagent_agent_router_test.go @@ -68,6 +68,7 @@ func TestRoutableDefRoutesToClassifiedModelE2E(t *testing.T) { RouterCategories: routerTaxonomyCategories(), RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { @@ -137,6 +138,7 @@ func TestPinnedInheritDefDoesNotRouteE2E(t *testing.T) { RouterCategories: routerTaxonomyCategories(), // router ON, but the pinned def must not route RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { @@ -209,6 +211,7 @@ func TestRoutableDefHallucinatedCategoryFailSoftE2E(t *testing.T) { RouterCategories: routerTaxonomyCategories(), RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, Diagnostics: diag, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), diff --git a/internal/app/subagent_model_default_test.go b/internal/app/subagent_model_default_test.go index 953f1e893f..be83c6a8fd 100644 --- a/internal/app/subagent_model_default_test.go +++ b/internal/app/subagent_model_default_test.go @@ -585,12 +585,13 @@ func TestSubagentModelRoutesChildToCheapModel(t *testing.T) { models []string ) built, err := buildIsolated(t, ctx, Config{ - Workspace: workspace, - NoSoul: true, - Model: "gpt-5", - SubagentModel: cheapModel, - AllowAllTools: true, // auto-approve so the delegation turn runs unattended - envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), + Workspace: workspace, + NoSoul: true, + Model: "gpt-5", + SubagentModel: cheapModel, + AllowAllTools: true, // auto-approve so the delegation turn runs unattended + GuardrailsDisabled: true, + envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), // Strictly offline: refuse any (keyed) live model fetch ⇒ embedded floor. liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { diff --git a/internal/app/subagent_writable_agent_router_test.go b/internal/app/subagent_writable_agent_router_test.go index 0c95953d09..cd5555bdc3 100644 --- a/internal/app/subagent_writable_agent_router_test.go +++ b/internal/app/subagent_writable_agent_router_test.go @@ -52,6 +52,7 @@ func TestWritableRoutableDefFullBuildE2E(t *testing.T) { RouterCategories: routerTaxonomyCategories(), RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { diff --git a/internal/app/subprovider_test.go b/internal/app/subprovider_test.go index 5ada58dedd..58ea7ab0b3 100644 --- a/internal/app/subprovider_test.go +++ b/internal/app/subprovider_test.go @@ -363,10 +363,11 @@ func TestSubproviderHalfAFullBuildE2E(t *testing.T) { writeFile(t, agentsDir, "orspec.md", "---\nname: orspec\ndescription: runs on openrouter\nprovider: openrouter\ntools: [Read]\n---\nYou run on openrouter.\n") built, err := buildIsolated(t, ctx, Config{ - Workspace: workspace, - NoSoul: true, - AgentsDirs: []string{agentsDir}, - AllowAllTools: true, // --yolo: auto-approve the routed Subagent (no interactive gate) + Workspace: workspace, + NoSoul: true, + AgentsDirs: []string{agentsDir}, + AllowAllTools: true, // --yolo: auto-approve the routed Subagent (no interactive gate) + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{ "OPENAI_API_KEY": "sk-x", "OPENROUTER_API_KEY": "sk-x", diff --git a/internal/app/team_parallel_router_test.go b/internal/app/team_parallel_router_test.go index cb342e1f97..5b83ca853d 100644 --- a/internal/app/team_parallel_router_test.go +++ b/internal/app/team_parallel_router_test.go @@ -555,6 +555,7 @@ func routerE2ECfg(workspace string, parentCtor func() port.LLMProvider, enable f }, RouterDefaultCategory: "small", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "sk-x"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, _, _, _ string) port.LLMProvider { return parentCtor() }, From ac26927a34f851794ba297e0723c6f0fd1e4ff16 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:38:07 +0300 Subject: [PATCH 03/48] feat(permissions): add --permission-mode to the server roots mecated, mecak8s, and mecatequi take the named token and fail fast on an unknown one. --posture and --yolo keep resolving as before, each warning once with the replacement token, and combining either with --permission-mode is a startup error. mecated's root refusal fast path sees the token's posture half. The shipped allow-all defaults now declare their checker choice. The Helm chart passes --permission-mode=auto and either the new guardrails.model value or an explicit --guardrails=off. The mecatequi action gains a permission-mode input, keeps posture as a deprecated alias, and passes --guardrails off when no checker model is set; this repo's workflow uses the new input. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/actions/mecatequi/action.yml | 66 +++- .github/workflows/mecatequi.yml | 6 +- cmd/mecak8s/flags.go | 22 +- cmd/mecak8s/main.go | 1 + cmd/mecak8s/main_test.go | 2 + cmd/mecak8s/mcp_test.go | 2 +- cmd/mecak8s/permission_mode.go | 51 ++++ cmd/mecak8s/permission_mode_test.go | 161 ++++++++++ cmd/mecak8s/telemetry_test.go | 4 +- cmd/mecated/helpmeta.go | 5 +- cmd/mecated/main.go | 43 ++- cmd/mecated/permission_mode.go | 67 +++++ cmd/mecated/permission_mode_test.go | 211 +++++++++++++ cmd/mecatequi/flags.go | 18 +- cmd/mecatequi/main.go | 6 +- cmd/mecatequi/permission_mode.go | 51 ++++ cmd/mecatequi/permission_mode_test.go | 282 ++++++++++++++++++ cmd/mecatequi/run.go | 2 +- deploy/helm/mecak8s/chart_test.go | 45 ++- deploy/helm/mecak8s/templates/deployment.yaml | 7 +- deploy/helm/mecak8s/values.schema.json | 14 + deploy/helm/mecak8s/values.yaml | 14 + 22 files changed, 1045 insertions(+), 35 deletions(-) create mode 100644 cmd/mecak8s/permission_mode.go create mode 100644 cmd/mecak8s/permission_mode_test.go create mode 100644 cmd/mecated/permission_mode.go create mode 100644 cmd/mecated/permission_mode_test.go create mode 100644 cmd/mecatequi/permission_mode.go create mode 100644 cmd/mecatequi/permission_mode_test.go diff --git a/.github/actions/mecatequi/action.yml b/.github/actions/mecatequi/action.yml index d3ac0ff2a1..20b80501da 100644 --- a/.github/actions/mecatequi/action.yml +++ b/.github/actions/mecatequi/action.yml @@ -46,7 +46,7 @@ # version — there is no version input (matlatl has none either). # # OMITTED INPUT — the ask-reviewer policy file. --subagent-ask-reviewer is surfaced (see -# the input) so a posture:auto run can adjudicate a child's read-only substitution instead +# the input) so an auto-mode run can adjudicate a child's read-only substitution instead # of silently auto-denying it, but --subagent-ask-reviewer-policy (a TRUSTED rubric file # whose CONTENT replaces the built-in rubric) is NOT surfaced: it grants the reviewer a # rule set the operator would have to author and check into the repo, which is a deliberate @@ -124,13 +124,24 @@ inputs: description: Session workspace root (must be a git repository so the diff can be computed). required: false default: ${{ github.workspace }} + permission-mode: + description: >- + Permission mode (ADR 0365) → --permission-mode: one of plan, default, accept-edits, + trusted, trusted-accept-edits, auto, yolo. Empty (the input default) resolves to + "auto", the documented CI mode (allow-all, child injection-defence ON), unless the + deprecated `posture` input is set. "default" would CANCEL the run on the first + mutate because a headless run has no approver. auto and yolo need a checker choice; + see `guardrails-model`. Setting both this and `posture` fails the step. + required: false + default: "" posture: description: >- - Operator posture ladder (strict < trusted < auto < yolo). Default "auto" — the - documented CI posture (allow-all, child injection-defence ON). "strict" would - CANCEL the run on the first mutate because a headless run has no approver. + DEPRECATED alias for `permission-mode`, kept for one release → --posture (the + binary WARNs). Used only when set non-empty; setting it together with + `permission-mode` fails the step. Migrate `posture: "auto"` to + `permission-mode: "auto"`. required: false - default: "auto" + default: "" timeout: description: >- Wall-clock bound on the whole run (e.g. 40m); the primary cost ceiling for a @@ -185,17 +196,24 @@ inputs: guardrails-model: description: >- GUARDRAILS (issue #27) checker model id / alias inspecting outbound args + inbound - results. Empty disables guardrails. + results → --guardrails-model. mecatequi refuses an allow-all permission mode (auto, + yolo) with no checker unless the opt-out is explicit, so this action always declares + the choice: a non-empty value passes --guardrails-model; empty (default) passes + --guardrails off, a DELIBERATE choice to run unsupervised with nothing inspecting + tool content. The kill-switch also disables a guardrail model slot from settings, + so name the checker here if you want one. required: false default: "" subagent-ask-reviewer: description: >- - OPT-IN headless ask reviewer (issue #31) → --subagent-ask-reviewer: model id / alias - of a tool-less one-turn reviewer that adjudicates a CHILD permission ask the headless - auto-deny would otherwise reject (so a posture:auto run whose subagent wants a - read-only $(...) substitution is reviewed rather than silently denied). Empty (default) - = no reviewer (children auto-deny). The TRUSTED policy-rubric file is NOT an input — - see the action header. + Headless ask reviewer (issue #31) → --subagent-ask-reviewer: model id / alias of a + tool-less one-turn reviewer that adjudicates a CHILD permission ask the headless + auto-deny would otherwise reject (so an auto-mode run whose subagent wants a + read-only $(...) substitution is reviewed rather than silently denied). Empty + (default) omits the flag: in the auto and yolo modes the reviewer is then ON by + default (ask-reviewer model slot, else the session model); in other modes children + auto-deny. "off" disables it explicitly. The TRUSTED policy-rubric file is NOT an + input — see the action header. required: false default: "" subagent-ask-reviewer-max-denies: @@ -365,6 +383,7 @@ runs: MQ_UNTRUSTED: ${{ inputs.untrusted }} MQ_INSTRUCTIONS: ${{ inputs.instructions }} MQ_WORKSPACE: ${{ inputs.workspace }} + MQ_PERMISSION_MODE: ${{ inputs.permission-mode }} MQ_POSTURE: ${{ inputs.posture }} MQ_TIMEOUT: ${{ inputs.timeout }} MQ_MAX_RUN_TOKENS: ${{ inputs.max-run-tokens }} @@ -407,10 +426,23 @@ runs: # Build the argv as an ARRAY from env values — never string-interpolated. Each # event-derived value crosses as a discrete token, so no value can be re-parsed # as a flag or a shell metacharacter. + # Permission mode: `permission-mode` replaces the deprecated `posture` input. Both + # set is ambiguous, so fail rather than guess; neither set is the documented CI mode. + if [ -n "${MQ_PERMISSION_MODE}" ] && [ -n "${MQ_POSTURE}" ]; then + echo "::error::both permission-mode and the deprecated posture input are set; pass only permission-mode." + exit 1 + fi + if [ -n "${MQ_POSTURE}" ]; then + echo "::warning::the posture input is deprecated; use permission-mode instead." + permission_args=( --posture "${MQ_POSTURE}" ) + else + permission_args=( --permission-mode "${MQ_PERMISSION_MODE:-auto}" ) + fi + args=( --prompt-file "${MQ_PROMPT_FILE}" --workspace "${MQ_WORKSPACE}" - --posture "${MQ_POSTURE}" + "${permission_args[@]}" --timeout "${MQ_TIMEOUT}" --headless=true --out-diff "${MQ_OUT_DIFF}" @@ -426,7 +458,13 @@ runs: [ -n "${MQ_DEFAULT_MODEL}" ] && args+=( --default-model "${MQ_DEFAULT_MODEL}" ) [ "${openai_on}" = "true" ] && args+=( --openai ) [ -n "${MQ_OPENAI_BASE_URL}" ] && args+=( --openai-base-url "${MQ_OPENAI_BASE_URL}" ) - [ -n "${MQ_GUARDRAILS_MODEL}" ] && args+=( --guardrails-model "${MQ_GUARDRAILS_MODEL}" ) + # Checker choice is ALWAYS declared: a named checker, or the explicit unsupervised + # kill-switch (an allow-all mode with neither is refused at startup). + if [ -n "${MQ_GUARDRAILS_MODEL}" ]; then + args+=( --guardrails-model "${MQ_GUARDRAILS_MODEL}" ) + else + args+=( --guardrails off ) + fi [ -n "${MQ_ASK_REVIEWER}" ] && args+=( --subagent-ask-reviewer "${MQ_ASK_REVIEWER}" ) [ -n "${MQ_ASK_REVIEWER_MAX_DENIES}" ] && args+=( --subagent-ask-reviewer-max-denies "${MQ_ASK_REVIEWER_MAX_DENIES}" ) diff --git a/.github/workflows/mecatequi.yml b/.github/workflows/mecatequi.yml index 6595efdecf..dc6d549356 100644 --- a/.github/workflows/mecatequi.yml +++ b/.github/workflows/mecatequi.yml @@ -2,7 +2,7 @@ # mecatequi — the LIVE workflow for THIS repo (mecatl). Private repo, internal posture. # # To run it: label an issue `mecatequi`, OR comment `@mecatequi` on an issue. The agent -# runs a single-shot mecatequi pass over the issue text (untrusted, posture:auto) against +# runs a single-shot mecatequi pass over the issue text (untrusted, permission-mode auto) against # OpenRouter, and the publish job opens a PR (or posts an honest comment) with the result. # # Unlike .github/workflows/mecatequi-example.yml (the inert template), this file is REAL: @@ -221,7 +221,9 @@ jobs: with: prompt-file: ${{ steps.prompt.outputs.prompt-file }} untrusted: "true" - posture: "auto" + permission-mode: "auto" + # No guardrails-model: the action passes --guardrails off, a deliberate + # unsupervised choice for this private, split-privilege CI run. # Use `model` (per-session passthrough), NOT `default-model`: a deployment # default is validated against the embedded models.dev catalog at startup, and # claude-sonnet-4.6 is newer than that snapshot (it would fail "not catalogued"). diff --git a/cmd/mecak8s/flags.go b/cmd/mecak8s/flags.go index 17b5fe6fea..ed317e1c5c 100644 --- a/cmd/mecak8s/flags.go +++ b/cmd/mecak8s/flags.go @@ -240,6 +240,12 @@ type config struct { // lets CLI out-rank the operator-global settings.yaml posture: key. posture string postureFlagSet bool + // permissionMode is the raw --permission-mode token (ADR 0365), validated at + // parse time. Empty (the default) leaves the deprecated --posture default + // "auto" in force, so an unconfigured pod keeps posture auto with the default + // session mode and operator YAML can still override it. + permissionMode string + permissionModeFlagSet bool // Reasoning-effort tier: operator-tier reasoning-effort default ("" = // unset, the provider's own default applies). reasoningEffortFlagSet records an @@ -444,7 +450,7 @@ func parseFlags(argv []string) (config, error) { fs.BoolVar(&cfg.headless, "headless", true, "Run without an interactive permission approver. Child permission requests are denied unless --subagent-ask-reviewer handles them") // Headless ask reviewer (issue #31). - fs.StringVar(&cfg.subagentAskReviewer, "subagent-ask-reviewer", "", "Model ID or alias for reviewing child permission requests in headless mode. Empty disables the reviewer") + fs.StringVar(&cfg.subagentAskReviewer, "subagent-ask-reviewer", "", "Model ID or alias for reviewing child permission requests in headless mode. Empty leaves the reviewer off, except that the auto and yolo permission modes turn it on by default (ask-reviewer model slot, else the session model); off disables it explicitly") fs.IntVar(&cfg.subagentAskReviewerMaxDenies, "subagent-ask-reviewer-max-denies", agent.DefaultAskReviewMaxDenies, "Consecutive non-allow outcomes that disable the reviewer for the run. Values less than or equal to zero use the default") fs.StringVar(&cfg.subagentAskReviewerPolicyFile, "subagent-ask-reviewer-policy", "", "Path to a trusted policy rubric for --subagent-ask-reviewer. Replaces the built-in rubric; an unreadable file prevents startup") @@ -457,7 +463,8 @@ func parseFlags(argv []string) (config, error) { fs.StringVar(&cfg.subagentModel, "subagent-model", "", "Default model for child agents without their own model. Empty inherits --model") // Posture: DEFAULT "auto" (the recommended UNATTENDED single-tenant tier). - fs.StringVar(&cfg.posture, "posture", "auto", "Permission posture: strict prompts for mutations; trusted honors project allow rules; auto allows tools by default and relaxes main shell substitutions while child injection defenses remain enabled; yolo also runs child command substitutions automatically. Deny rules and configured ask rules still apply. auto and yolo require MECATL_SANDBOX when running as root") + fs.StringVar(&cfg.permissionMode, "permission-mode", "", permissionModeHelp) + fs.StringVar(&cfg.posture, "posture", "auto", "DEPRECATED: use --permission-mode. Permission posture: strict prompts for mutations; trusted honors project allow rules; auto allows tools by default and relaxes main shell substitutions while child injection defenses remain enabled; yolo also runs child command substitutions automatically. Deny rules and configured ask rules still apply. auto and yolo require MECATL_SANDBOX when running as root") // Reasoning-effort tier: operator-tier only; help text verbatim from mecated. fs.StringVar(&cfg.reasoningEffort, "reasoning-effort", "", @@ -494,7 +501,7 @@ func parseFlags(argv []string) (config, error) { fs.Var(&cfg.permissionConfigs, "permission-config", "Trusted permission YAML file. Repeatable") fs.BoolVar(&cfg.permissionsConventional, "permissions-conventional", true, "Discover project and user permission settings for each session") fs.BoolVar(&cfg.importClaudePermissions, "import-claude-permissions", false, "Import compatible Claude Code permission settings") - fs.BoolVar(&cfg.trustProject, "trust-project", false, "Honor a discovered project's allow rules. Deny and ask rules are always honored; equivalent to --posture=trusted") + fs.BoolVar(&cfg.trustProject, "trust-project", false, "Honor a discovered project's allow rules. Deny and ask rules are always honored; raises the posture to at least trusted and combines with --permission-mode") // Fan-out / teams toggles. fs.BoolVar(&cfg.enableParallel, "enable-parallel", false, "Enable the Parallel tool for isolated child branches") @@ -546,6 +553,8 @@ func parseFlags(argv []string) (config, error) { switch fl.Name { case "posture": cfg.postureFlagSet = true + case "permission-mode": + cfg.permissionModeFlagSet = true case "shell": cfg.shellFlagSet = true case "reasoning-effort": @@ -563,6 +572,9 @@ func parseFlags(argv []string) (config, error) { cfg.defaultProviderFlagSet = true } }) + if err := validatePermissionModeFlags(cfg); err != nil { + return config{}, err + } resolvedShell, err := cliconfig.ResolveCommandRunnerConfig(cfg.shell, cfg.shellFlagSet, cfg.permissionsConventional, cfg.permissionConfigs) if err != nil { return config{}, fmt.Errorf("command runner configuration: %w", err) @@ -815,6 +827,10 @@ func appConfig(cfg config, diag port.Diagnostics, obs observability) app.Config PermissionConfigs: cfg.permissionConfigs, Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, + // Permission mode (ADR 0365): an explicit token out-ranks the deprecated + // --posture (default auto) in app.Build's foldPermissionMode. + PermissionMode: cfg.permissionMode, + PermissionModeFlagSet: cfg.permissionModeFlagSet, // Reasoning-effort tier: operator-tier only; reasoningEffortFlagSet // lets CLI out-rank the operator-global settings.yaml reasoning-effort: key // (folded by foldOperatorReasoningEffort in app.Build, like posture). diff --git a/cmd/mecak8s/main.go b/cmd/mecak8s/main.go index f37eb3046c..74b8be00c4 100644 --- a/cmd/mecak8s/main.go +++ b/cmd/mecak8s/main.go @@ -75,6 +75,7 @@ func run() error { diag = slogdiag.New(os.Stderr, true, port.LevelDebug) } cfg.diagnostics = diag + warnDeprecatedPermissionFlags(diag, cfg) ctx, stop := signalCtx() defer stop() diff --git a/cmd/mecak8s/main_test.go b/cmd/mecak8s/main_test.go index 7549e76456..686daa502c 100644 --- a/cmd/mecak8s/main_test.go +++ b/cmd/mecak8s/main_test.go @@ -453,6 +453,7 @@ func TestBuildOverRedisDrivesRunToCompletion(t *testing.T) { RedisAllowPlaintext: true, Interactive: false, // mecak8s headless default (Interactive=!headless) Posture: app.PostureAuto, + GuardrailsDisabled: true, // allow-all declares its checker choice (ADR 0365) PermissionsConventional: false, AgentsConventional: false, Diagnostics: port.NopDiagnostics{}, @@ -626,6 +627,7 @@ func TestDrainHTTPRouting(t *testing.T) { func TestServeWiresSeparateDrainListener(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", + "--guardrails=off", // the auto default must declare its checker choice (ADR 0365) "--grpc-addr", freeLoopbackPort(t), "--http-addr", freeLoopbackPort(t), "--drain-addr", freeLoopbackPort(t), diff --git a/cmd/mecak8s/mcp_test.go b/cmd/mecak8s/mcp_test.go index e4b1e1e16b..21622db97e 100644 --- a/cmd/mecak8s/mcp_test.go +++ b/cmd/mecak8s/mcp_test.go @@ -60,7 +60,7 @@ func TestMecak8sBuildDiscoversOperatorMCPSettings(t *testing.T) { if err := os.WriteFile(explicit, []byte("mcp:\n mode: global\n servers:\n - name: explicit\n url: https://mcp.example/mcp\n auth: {mode: none}\n"), 0o600); err != nil { t.Fatal(err) } - cfg, err = parseFlags([]string{"--permission-config", explicit}) + cfg, err = parseFlags([]string{"--permission-config", explicit, "--guardrails=off"}) if err != nil { t.Fatal(err) } diff --git a/cmd/mecak8s/permission_mode.go b/cmd/mecak8s/permission_mode.go new file mode 100644 index 0000000000..49b029eb35 --- /dev/null +++ b/cmd/mecak8s/permission_mode.go @@ -0,0 +1,51 @@ +package main + +import ( + "context" + "fmt" + "strings" + + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/app" +) + +// permissionModeHelp is the --permission-mode usage line (ADR 0365). It names +// both halves a token sets and their lifetimes, and lists every valid token from +// the composition table so help and parsing cannot drift. +var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + + ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; trusted for trusted and trusted-accept-edits; auto; yolo), " + + "and the session mode new sessions start in, which each session may change. Default: auto (posture auto, default session mode). " + + "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model or the guardrail model slot) or an explicit --guardrails off, and require MECATL_SANDBOX when running as root. " + + "Deny rules and configured ask rules still apply. Replaces the deprecated --posture; --trust-project still combines with it" + +// validatePermissionModeFlags fails fast on an unknown --permission-mode token +// and on a --permission-mode combined with the deprecated --posture alias. +func validatePermissionModeFlags(cfg config) error { + if !cfg.permissionModeFlagSet { + return nil + } + if _, err := app.ParsePermissionMode(cfg.permissionMode); err != nil { + return fmt.Errorf("--permission-mode: %w", err) + } + if cfg.postureFlagSet { + return fmt.Errorf("--permission-mode and --posture are both set: pass only --permission-mode (--posture is its deprecated alias)") + } + return nil +} + +// warnDeprecatedPermissionFlags emits exactly one deprecation WARN when the +// operator passed the deprecated --posture explicitly. The --posture DEFAULT +// (auto) is not a use of the alias and stays silent. +func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { + if diag == nil || !cfg.postureFlagSet { + return + } + replacement := "default" + if tok, ok := app.PermissionModeForPair(app.ParsePosture(cfg.posture), session.ModeDefault); ok { + replacement = tok.Name + } + diag.Log(context.Background(), port.LevelWarn, + "--posture is DEPRECATED; use --permission-mode instead (ADR 0365)", + "posture", cfg.posture, "replacement", "--permission-mode "+replacement) +} diff --git a/cmd/mecak8s/permission_mode_test.go b/cmd/mecak8s/permission_mode_test.go new file mode 100644 index 0000000000..cf23662229 --- /dev/null +++ b/cmd/mecak8s/permission_mode_test.go @@ -0,0 +1,161 @@ +package main + +import ( + "bytes" + "context" + "log/slog" + "strings" + "testing" + + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/slogdiag" + "github.com/stacklok/mecatl/internal/app" +) + +// k8sPair returns the (posture, default session mode) pair and the app.Config +// that a mecak8s argv hands to app.Build. +func k8sPair(t *testing.T, argv ...string) (app.Posture, session.PermissionMode, app.Config) { + t.Helper() + cfg, err := parseFlags(argv) + if err != nil { + t.Fatalf("parseFlags(%q): %v", argv, err) + } + ac := appConfig(cfg, port.NopDiagnostics{}, observability{}) + if ac.PermissionModeFlagSet { + tok, err := app.ParsePermissionMode(ac.PermissionMode) + if err != nil { + t.Fatalf("appConfig carried an invalid token %q: %v", ac.PermissionMode, err) + } + return app.ResolveAliasPosture(tok.Posture, ac.AllowAllTools, ac.TrustProject), tok.SessionMode, ac + } + mode := ac.DefaultSessionMode + if mode == "" { + mode = session.ModeDefault + } + return app.ResolveAuthoritativePosture(ac), mode, ac +} + +func k8sDeprecationWarnings(t *testing.T, argv ...string) []string { + t.Helper() + cfg, err := parseFlags(argv) + if err != nil { + t.Fatalf("parseFlags(%q): %v", argv, err) + } + var buf bytes.Buffer + warnDeprecatedPermissionFlags(slogdiag.NewFromLogger(slog.New(slog.NewTextHandler(&buf, nil))), cfg) + var out []string + for _, line := range strings.Split(buf.String(), "\n") { + if strings.Contains(line, "level=WARN") && strings.Contains(line, "DEPRECATED") { + out = append(out, line) + } + } + return out +} + +func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { + for _, tc := range []struct{ posture, token string }{ + {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, + } { + t.Run(tc.posture, func(t *testing.T) { + aliasPosture, aliasMode, _ := k8sPair(t, "--posture", tc.posture) + tokPosture, tokMode, _ := k8sPair(t, "--permission-mode", tc.token) + if aliasPosture != tokPosture || aliasMode != tokMode { + t.Fatalf("--posture %s = (%s, %s), want the %q token's (%s, %s)", tc.posture, aliasPosture, aliasMode, tc.token, tokPosture, tokMode) + } + warns := k8sDeprecationWarnings(t, "--posture", tc.posture) + if len(warns) != 1 || !strings.Contains(warns[0], "--permission-mode "+tc.token) { + t.Fatalf("--posture %s deprecation WARNs = %q, want exactly one naming --permission-mode %s", tc.posture, warns, tc.token) + } + }) + } + // The --posture DEFAULT is not a use of the alias. + if warns := k8sDeprecationWarnings(t); len(warns) != 0 { + t.Fatalf("default mecak8s emitted deprecation WARNs: %q", warns) + } + if warns := k8sDeprecationWarnings(t, "--permission-mode", "auto"); len(warns) != 0 { + t.Fatalf("--permission-mode emitted deprecation WARNs: %q", warns) + } +} + +func TestADR_0365_AliasCombinationsStillResolve(t *testing.T) { + // Headless root: no token grants project trust, so strict plus explicit trust + // (today: trusted posture, TrustProject) must keep resolving as it does today. + posture, mode, ac := k8sPair(t, "--posture", "strict", "--trust-project") + if posture != app.PostureTrusted || mode != session.ModeDefault || !ac.TrustProject { + t.Fatalf("--posture strict --trust-project = (%s, %s, trust=%v), want (trusted, default, trust=true)", posture, mode, ac.TrustProject) + } + posture, _, ac = k8sPair(t, "--posture", "yolo", "--trust-project") + if posture != app.PostureYolo || !ac.TrustProject { + t.Fatalf("--posture yolo --trust-project = (%s, trust=%v), want (yolo, trust=true)", posture, ac.TrustProject) + } + posture, _, ac = k8sPair(t, "--permission-mode", "auto", "--trust-project") + if posture != app.PostureAuto || !ac.TrustProject { + t.Fatalf("--permission-mode auto --trust-project = (%s, trust=%v), want (auto, trust=true)", posture, ac.TrustProject) + } +} + +func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { + posture, mode, ac := k8sPair(t) + if posture != app.PostureAuto || mode != session.ModeDefault { + t.Fatalf("default mecak8s = (%s, %s), want (auto, default)", posture, mode) + } + // The auto default stays a non-explicit --posture default, so operator YAML + // can still override it exactly as today. + if ac.Posture != app.PostureAuto || ac.PostureFlagSet || ac.PermissionModeFlagSet || ac.DefaultSessionMode != "" { + t.Fatalf("default app.Config posture=%s postureSet=%v modeSet=%v default=%q, want auto/false/false/empty", + ac.Posture, ac.PostureFlagSet, ac.PermissionModeFlagSet, ac.DefaultSessionMode) + } + if !ac.Headless || ac.Interactive || ac.TrustProject { + t.Fatalf("default mecak8s headless=%v interactive=%v trust=%v, want true/false/false", ac.Headless, ac.Interactive, ac.TrustProject) + } +} + +func TestADR_0365_BareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { + build := func(argv ...string) error { + cfg, err := parseFlags(argv) + if err != nil { + t.Fatalf("parseFlags(%q): %v", argv, err) + } + ac := appConfig(cfg, port.NopDiagnostics{}, observability{}) + ac.RedisURL = "" + ac.SchedulerEnabled = false + ac.SessionLeaseK8sNamespace = "" + ac.Workspace = t.TempDir() + ac.MockProvider = mockllm.New() + built, err := buildIsolated(t, context.Background(), ac) + if err == nil { + built.Close() + } + return err + } + err := build() + if err == nil || !strings.Contains(err.Error(), "no guardrails checker") || !strings.Contains(err.Error(), "--guardrails off") { + t.Fatalf("bare mecak8s Build err = %v, want the checker refusal naming --guardrails off", err) + } + if err := build("--guardrails=off"); err != nil { + t.Fatalf("mecak8s with an explicit --guardrails=off: %v", err) + } +} + +func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { + _, err := parseFlags([]string{"--permission-mode", "auto", "--posture", "auto"}) + if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { + t.Fatalf("--permission-mode with --posture err = %v, want a pass-one startup error", err) + } + _, err = parseFlags([]string{"--permission-mode", "bogus"}) + if err == nil { + t.Fatal("unknown --permission-mode token parsed without error") + } + for _, name := range app.PermissionModeNames() { + if !strings.Contains(err.Error(), name) { + t.Fatalf("unknown-token error %q does not name %q", err, name) + } + } + for _, want := range append(app.PermissionModeNames(), "process-wide", "new sessions") { + if !strings.Contains(permissionModeHelp, want) { + t.Fatalf("--permission-mode help lacks %q", want) + } + } +} diff --git a/cmd/mecak8s/telemetry_test.go b/cmd/mecak8s/telemetry_test.go index 08aef9faae..2474e55999 100644 --- a/cmd/mecak8s/telemetry_test.go +++ b/cmd/mecak8s/telemetry_test.go @@ -227,7 +227,8 @@ func TestTelemetryMetricsAddrServesPrometheus(t *testing.T) { // A fixed free loopback port so the scrape target is deterministic. free := freeLoopbackPort(t) cfg, err := parseFlags([]string{ - "--mock", // offline: no provider key in CI + "--mock", // offline: no provider key in CI + "--guardrails=off", // the auto default must declare its checker choice (ADR 0365) "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--metrics-addr", free, @@ -339,6 +340,7 @@ func TestTelemetryPushesRunMetricsOnExit(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", + "--guardrails=off", // the auto default must declare its checker choice (ADR 0365) "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--grpc-addr", "127.0.0.1:0", diff --git a/cmd/mecated/helpmeta.go b/cmd/mecated/helpmeta.go index 42a445bff4..a9a71a8c10 100644 --- a/cmd/mecated/helpmeta.go +++ b/cmd/mecated/helpmeta.go @@ -186,10 +186,11 @@ var flagMetaByFlag = map[string]flagMeta{ "no-shell": {group: groupTools, common: true, acp: acpInclude}, // ── Posture & permissions (both) ───────────────────────────────────── - "posture": {group: groupPermissions, common: true, acp: acpInclude}, + "permission-mode": {group: groupPermissions, common: true, acp: acpInclude}, + "posture": {group: groupPermissions, common: false, acp: acpInclude}, "deployment-id": {group: groupServer, common: false, acp: acpInclude}, "cors-origins": {group: groupSecurity, common: false, acp: acpExclude}, - "yolo": {group: groupPermissions, common: true, acp: acpInclude}, + "yolo": {group: groupPermissions, common: false, acp: acpInclude}, "trust-project": {group: groupPermissions, common: true, acp: acpInclude}, "permissions-conventional": {group: groupPermissions, common: true, acp: acpInclude}, "import-claude-permissions": {group: groupPermissions, common: false, acp: acpInclude}, diff --git a/cmd/mecated/main.go b/cmd/mecated/main.go index 1edcf9a450..99483030d4 100644 --- a/cmd/mecated/main.go +++ b/cmd/mecated/main.go @@ -512,6 +512,15 @@ type config struct { // postureFlagSet is true when --posture was passed explicitly (set after parse via // fs.Visit), so composition lets CLI out-rank the settings.yaml posture: key. postureFlagSet bool + // permissionMode is the raw --permission-mode token (ADR 0365), validated at + // parse time; permissionModeFlagSet records that it was passed explicitly, so + // composition (app.Build's foldPermissionMode) lets it out-rank every other + // posture source. --posture and --yolo are its deprecated aliases. + permissionMode string + permissionModeFlagSet bool + // yoloFlagSet records an explicit --yolo, for the deprecation WARN and the + // --permission-mode conflict check. + yoloFlagSet bool // reasoningEffort is the operator-tier reasoning-effort default: "" // or "auto" (unset → the provider default) or low/medium/high/xhigh/max. // Operator-tier only: the operator-global settings.yaml reasoning-effort: key @@ -1333,7 +1342,12 @@ func appConfig(cfg config, sink port.EventSink, recorder port.ToolCallRecorder, // YAML-only allow-all tier cannot escape it. Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - DeploymentID: cfg.deploymentID, + // Permission mode (ADR 0365): the named token writes both the posture and + // the default session mode; app.Build's foldPermissionMode resolves it + // ahead of the deprecated --posture/--yolo surface. + PermissionMode: cfg.permissionMode, + PermissionModeFlagSet: cfg.permissionModeFlagSet, + DeploymentID: cfg.deploymentID, // Reasoning-effort tier: operator-tier only; reasoningEffortFlagSet // lets CLI out-rank the operator-global settings.yaml reasoning-effort: key. ReasoningEffort: cfg.reasoningEffort, @@ -1387,6 +1401,7 @@ func appConfig(cfg config, sink port.EventSink, recorder port.ToolCallRecorder, // cyclomatic complexity bounded. A non-nil err is the root/no-sandbox refusal (a // fast path — app.Build re-checks it authoritatively as the fail-closed backstop). func applyPostureCLI(cfg config, diag port.Diagnostics) error { + warnDeprecatedPermissionFlags(diag, cfg) effPosture := app.ResolveAuthoritativePosture(posturePreCheckConfig(cfg, diag)) if !app.IsKnownPostureToken(cfg.posture) { slog.Warn("unknown --posture value; failing closed to strict", "value", cfg.posture) @@ -1414,13 +1429,15 @@ func applyPostureCLI(cfg config, diag port.Diagnostics) error { // --trust-project inputs. It does NOT need the provider/engine fields — app.Build owns // the authoritative resolution + the engine; this is only the early read. func posturePreCheckConfig(cfg config, diag port.Diagnostics) app.Config { - return app.Config{ + out := app.Config{ Workspace: cfg.workspace, PermissionsConventional: cfg.permissionsConventional, ImportClaudePermissions: cfg.importClaudePermissions, PermissionConfigs: cfg.permissionConfigs, Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, + PermissionMode: cfg.permissionMode, + PermissionModeFlagSet: cfg.permissionModeFlagSet, DeploymentID: cfg.deploymentID, AllowAllTools: cfg.allowAllTools, TrustProject: cfg.trustProject, @@ -1428,6 +1445,14 @@ func posturePreCheckConfig(cfg config, diag port.Diagnostics) app.Config { Interactive: !cfg.headless, Diagnostics: diag, } + // An explicit --permission-mode token's posture half is the explicit tier the + // fast path must see, so `--permission-mode yolo` as bare root hits the same + // refusal `--yolo` does. The token was validated at parse time. + if tok, err := app.ParsePermissionMode(cfg.permissionMode); cfg.permissionModeFlagSet && err == nil { + out.Posture = tok.Posture + out.PostureFlagSet = true + } + return out } // privilegedProcess reports the cmd-computed "root WITHOUT a declared sandbox" @@ -1828,7 +1853,7 @@ func parseFlagsModeOut(mode commandMode, argv []string, out io.Writer) (*flag.Fl // Shared model alias/slot flags (cliconfig): mecated uses the default help // wording, so a zero ModelFlagHelp is enough. cfg.modelAliases, cfg.modelAliasProviders, cfg.modelSlots = cliconfig.RegisterModelFlags(fs, cliconfig.ModelFlagHelp{}) - fs.StringVar(&cfg.subagentAskReviewer, "subagent-ask-reviewer", "", "model identifier or --model-alias for reviewing child permission requests in headless mode. An allow applies only to that request; denied or failed reviews deny it. Empty disables reviews.") + fs.StringVar(&cfg.subagentAskReviewer, "subagent-ask-reviewer", "", "model identifier or --model-alias for reviewing child permission requests in headless mode. An allow applies only to that request; denied or failed reviews deny it. Empty leaves reviews off, except that a headless auto or yolo permission mode turns them on by default (ask-reviewer model slot, else the session model); off disables reviews explicitly.") fs.IntVar(&cfg.subagentAskReviewerMaxDenies, "subagent-ask-reviewer-max-denies", agent.DefaultAskReviewMaxDenies, "maximum consecutive denied, failed, or timed-out child-permission reviews before later requests are automatically denied. An allowed review resets the count. Values at or below 0 use the default of 3.") fs.StringVar(&cfg.subagentAskReviewerPolicyFile, "subagent-ask-reviewer-policy", "", "path to a trusted policy file that replaces the built-in child-permission review rubric. Startup fails if the file is unreadable.") fs.BoolVar(&cfg.subagentModelRouter, "subagent-model-router", false, "set explicitly to false to disable the configured subagent model router. The router selects a model for eligible plain subagent delegations; failures use the default model.") @@ -1861,10 +1886,11 @@ func parseFlagsModeOut(mode commandMode, argv []string, out io.Writer) (*flag.Fl fs.BoolVar(&cfg.permissionsConventional, "permissions-conventional", true, "load project and user permission settings for each session. Enabled by default. Project allow rules require --trust-project; project deny and ask rules always apply.") fs.BoolVar(&cfg.importClaudePermissions, "import-claude-permissions", false, "also load supported Claude Code permission settings when --permissions-conventional is enabled. Unsupported or invalid rules are ignored with a log entry.") fs.BoolVar(&cfg.trustProject, "trust-project", false, "apply allow rules from a discovered project permission configuration. Project deny and ask rules always apply. Disabled by default because project allow rules can approve tool calls.") + fs.StringVar(&cfg.permissionMode, "permission-mode", "", permissionModeHelp) fs.BoolVar(&cfg.allowAllTools, "yolo", false, - "alias for --posture=yolo. Allows tools server-wide and lets child command substitutions run automatically. Deny rules and configured ask rules still apply. Intended only for isolated, ephemeral, single-tenant environments. Refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1.") + "DEPRECATED: use --permission-mode yolo. Alias for --posture=yolo. Allows tools server-wide and lets child command substitutions run automatically. Deny rules and configured ask rules still apply. Intended only for isolated, ephemeral, single-tenant environments. Refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1.") fs.StringVar(&cfg.posture, "posture", "", - "permission posture: strict prompts mutations; trusted applies project allow rules; auto allows tools and relaxes main shell substitutions; yolo also runs child command substitutions. Deny rules and configured ask rules still apply. strict is the default. --trust-project and --yolo select trusted and yolo. auto and yolo are refused for root outside MECATL_SANDBOX.") + "DEPRECATED: use --permission-mode. Permission posture: strict prompts mutations; trusted applies project allow rules; auto allows tools and relaxes main shell substitutions; yolo also runs child command substitutions. Deny rules and configured ask rules still apply. strict is the default. --trust-project and --yolo select trusted and yolo. auto and yolo are refused for root outside MECATL_SANDBOX.") fs.StringVar(&cfg.deploymentID, "deployment-id", "", fmt.Sprintf("optional opaque deployment label returned by GetCompatibilityInfo. Mecatl never derives it from host or environment values. Printable single-line text only, up to %d bytes.", maxDeploymentIDLen)) @@ -1942,6 +1968,9 @@ func parseFlagsModeOut(mode commandMode, argv []string, out io.Writer) (*flag.Fl // composition can let CLI out-rank the operator-global settings.yaml posture: key // and WARN if an alias raised above an explicit lower --posture. recordExplicitFlags(fs, &cfg) + if err := validatePermissionModeFlags(cfg); err != nil { + return fs, config{}, err + } resolvedShell, err := cliconfig.ResolveCommandRunnerConfig(cfg.shell, cfg.shellFlagSet, cfg.permissionsConventional, cfg.permissionConfigs) if err != nil { return fs, config{}, fmt.Errorf("command runner configuration: %w", err) @@ -2034,6 +2063,10 @@ func recordExplicitFlags(fs *flag.FlagSet, cfg *config) { switch f.Name { case "posture": cfg.postureFlagSet = true + case "permission-mode": + cfg.permissionModeFlagSet = true + case "yolo": + cfg.yoloFlagSet = true case "shell": cfg.shellFlagSet = true case "subagent-model-router": diff --git a/cmd/mecated/permission_mode.go b/cmd/mecated/permission_mode.go new file mode 100644 index 0000000000..f17a003112 --- /dev/null +++ b/cmd/mecated/permission_mode.go @@ -0,0 +1,67 @@ +package main + +import ( + "context" + "fmt" + "strings" + + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/app" +) + +// permissionModeHelp is the --permission-mode usage line (ADR 0365). It names +// both halves a token sets and their lifetimes, and lists every valid token from +// the composition table so help and parsing cannot drift. +var permissionModeHelp = "permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + + ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; trusted for trusted and trusted-accept-edits; auto; yolo), " + + "and the session mode new sessions start in, which each session may change. Default: default. " + + "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model) or an explicit --guardrails off, and are refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1. " + + "Deny rules and configured ask rules still apply. Replaces the deprecated --posture and --yolo; --trust-project still combines with it." + +// validatePermissionModeFlags fails fast on an unknown --permission-mode token +// and on a --permission-mode combined with one of its deprecated aliases, so the +// operator never has to guess which of two permission sources won. +func validatePermissionModeFlags(cfg config) error { + if !cfg.permissionModeFlagSet { + return nil + } + if _, err := app.ParsePermissionMode(cfg.permissionMode); err != nil { + return fmt.Errorf("--permission-mode: %w", err) + } + if cfg.postureFlagSet { + return fmt.Errorf("--permission-mode and --posture are both set: pass only --permission-mode (--posture is its deprecated alias)") + } + if cfg.yoloFlagSet { + return fmt.Errorf("--permission-mode and --yolo are both set: pass only --permission-mode (--yolo is a deprecated alias for --permission-mode yolo)") + } + return nil +} + +// warnDeprecatedPermissionFlags emits exactly one deprecation WARN per +// deprecated alias the operator passed, naming the --permission-mode token that +// replaces it. The aliases still resolve exactly as before. +func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { + if diag == nil { + return + } + if cfg.postureFlagSet { + diag.Log(context.Background(), port.LevelWarn, + "--posture is DEPRECATED; use --permission-mode instead (ADR 0365)", + "posture", cfg.posture, "replacement", "--permission-mode "+postureReplacementToken(cfg.posture)) + } + if cfg.yoloFlagSet { + diag.Log(context.Background(), port.LevelWarn, + "--yolo is DEPRECATED; use --permission-mode yolo instead (ADR 0365)", + "replacement", "--permission-mode yolo") + } +} + +// postureReplacementToken names the token equivalent to a legacy --posture +// value with the default session mode (strict maps to default). +func postureReplacementToken(raw string) string { + if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { + return tok.Name + } + return "default" +} diff --git a/cmd/mecated/permission_mode_test.go b/cmd/mecated/permission_mode_test.go new file mode 100644 index 0000000000..27bccce5e8 --- /dev/null +++ b/cmd/mecated/permission_mode_test.go @@ -0,0 +1,211 @@ +package main + +import ( + "log/slog" + "strings" + "testing" + + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/slogdiag" + "github.com/stacklok/mecatl/internal/app" +) + +// resolvedPair is the (posture, default session mode) pair a mecated argv +// produces, read through the same fast-path resolver applyPostureCLI uses and +// the app.Config the root hands to app.Build. +func resolvedPair(t *testing.T, argv ...string) (app.Posture, session.PermissionMode, app.Config) { + t.Helper() + cfg, err := parseFlags(argv) + if err != nil { + t.Fatalf("parseFlags(%q): %v", argv, err) + } + posture := app.ResolveAuthoritativePosture(posturePreCheckConfig(cfg, port.NopDiagnostics{})) + mode := session.ModeDefault + ac := appConfig(cfg, nil, nil, nil, nil, nil) + if ac.PermissionModeFlagSet { + tok, err := app.ParsePermissionMode(ac.PermissionMode) + if err != nil { + t.Fatalf("appConfig carried an invalid token %q: %v", ac.PermissionMode, err) + } + mode = tok.SessionMode + } else if ac.DefaultSessionMode != "" { + mode = ac.DefaultSessionMode + } + return posture, mode, ac +} + +// deprecationWarnings runs the real startup posture surface (applyPostureCLI) +// and returns the deprecation WARN lines it logged. +func deprecationWarnings(t *testing.T, argv ...string) []string { + t.Helper() + cfg, err := parseFlags(argv) + if err != nil { + t.Fatalf("parseFlags(%q): %v", argv, err) + } + logs := captureLogs(t) + if err := applyPostureCLI(cfg, slogdiag.NewFromLogger(slog.Default())); err != nil { + t.Fatalf("applyPostureCLI(%q): %v", argv, err) + } + var out []string + for _, line := range strings.Split(logs(), "\n") { + if strings.Contains(line, "level=WARN") && strings.Contains(line, "DEPRECATED") { + out = append(out, line) + } + } + return out +} + +func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { + cases := []struct { + name string + alias []string + token string + }{ + {"posture strict", []string{"--posture", "strict"}, "default"}, + {"posture trusted", []string{"--posture", "trusted"}, "trusted"}, + {"posture auto", []string{"--posture", "auto"}, "auto"}, + {"posture yolo", []string{"--posture", "yolo"}, "yolo"}, + {"yolo", []string{"--yolo"}, "yolo"}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + aliasPosture, aliasMode, _ := resolvedPair(t, tc.alias...) + tokPosture, tokMode, _ := resolvedPair(t, "--permission-mode", tc.token) + if aliasPosture != tokPosture || aliasMode != tokMode { + t.Fatalf("%q resolved to (%s, %s), want the %q token's (%s, %s)", + tc.alias, aliasPosture, aliasMode, tc.token, tokPosture, tokMode) + } + warns := deprecationWarnings(t, tc.alias...) + if len(warns) != 1 { + t.Fatalf("%q emitted %d deprecation WARNs, want exactly 1: %q", tc.alias, len(warns), warns) + } + if !strings.Contains(warns[0], "--permission-mode") { + t.Fatalf("deprecation WARN does not name --permission-mode: %s", warns[0]) + } + if !strings.Contains(warns[0], "--permission-mode "+tc.token) { + t.Fatalf("deprecation WARN does not name the replacement token %q: %s", tc.token, warns[0]) + } + }) + } + // The replacement itself is not deprecated. + if warns := deprecationWarnings(t, "--permission-mode", "auto"); len(warns) != 0 { + t.Fatalf("--permission-mode emitted deprecation WARNs: %q", warns) + } +} + +func TestADR_0365_AliasCombinationsStillResolve(t *testing.T) { + cases := []struct { + name string + argv []string + wantPosture app.Posture + wantTrust bool + wantAllow bool + }{ + // Interactive root: --trust-project raises an explicit strict to trusted, today's MAX fold. + {"posture strict trust-project interactive", []string{"--posture", "strict", "--trust-project"}, app.PostureTrusted, true, false}, + // Headless root: no token grants trust on headless, so yolo plus explicit trust has no single-token spelling. + {"yolo trust-project headless", []string{"--headless", "--yolo", "--trust-project"}, app.PostureYolo, true, true}, + {"posture auto yolo", []string{"--posture", "auto", "--yolo"}, app.PostureYolo, false, true}, + // --trust-project is not deprecated and still combines with the new flag. + {"permission-mode auto trust-project headless", []string{"--headless", "--permission-mode", "auto", "--trust-project"}, app.PostureAuto, true, false}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + posture, mode, ac := resolvedPair(t, tc.argv...) + if posture != tc.wantPosture { + t.Fatalf("%q posture = %s, want %s", tc.argv, posture, tc.wantPosture) + } + if mode != session.ModeDefault { + t.Fatalf("%q session mode = %s, want default", tc.argv, mode) + } + if ac.TrustProject != tc.wantTrust { + t.Fatalf("%q TrustProject = %v, want %v", tc.argv, ac.TrustProject, tc.wantTrust) + } + if ac.AllowAllTools != tc.wantAllow { + t.Fatalf("%q AllowAllTools = %v, want %v", tc.argv, ac.AllowAllTools, tc.wantAllow) + } + }) + } +} + +func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { + for _, tc := range []struct { + name string + argv []string + }{ + {"interactive", nil}, + {"headless", []string{"--headless"}}, + } { + t.Run(tc.name, func(t *testing.T) { + posture, mode, ac := resolvedPair(t, tc.argv...) + if posture != app.PostureStrict || mode != session.ModeDefault { + t.Fatalf("unconfigured %s mecated = (%s, %s), want (strict, default)", tc.name, posture, mode) + } + if ac.Posture != app.PostureStrict || ac.PostureFlagSet || ac.PermissionModeFlagSet || ac.PermissionMode != "" || ac.DefaultSessionMode != "" { + t.Fatalf("unconfigured %s app.Config carries a permission choice: posture=%s postureSet=%v modeSet=%v mode=%q default=%q", + tc.name, ac.Posture, ac.PostureFlagSet, ac.PermissionModeFlagSet, ac.PermissionMode, ac.DefaultSessionMode) + } + if ac.AllowAllTools || ac.TrustProject { + t.Fatalf("unconfigured %s mecated raised allow-all=%v trust=%v", tc.name, ac.AllowAllTools, ac.TrustProject) + } + if warns := deprecationWarnings(t, tc.argv...); len(warns) != 0 { + t.Fatalf("unconfigured %s mecated emitted deprecation WARNs: %q", tc.name, warns) + } + }) + } +} + +func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { + for _, argv := range [][]string{ + {"--permission-mode", "auto", "--posture", "auto"}, + {"--posture", "strict", "--permission-mode", "default"}, + {"--permission-mode", "yolo", "--yolo"}, + } { + _, err := parseFlags(argv) + if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { + t.Fatalf("parseFlags(%q) err = %v, want a pass-one startup error", argv, err) + } + } + _, err := parseFlags([]string{"--permission-mode", "bogus"}) + if err == nil { + t.Fatal("unknown --permission-mode token parsed without error") + } + for _, name := range app.PermissionModeNames() { + if !strings.Contains(err.Error(), name) { + t.Fatalf("unknown-token error %q does not name valid token %q", err, name) + } + } + // --trust-project is not an alias and combines freely. + if _, err := parseFlags([]string{"--permission-mode", "default", "--trust-project"}); err != nil { + t.Fatalf("--permission-mode with --trust-project: %v", err) + } +} + +func TestADR_0365_PermissionModeHitsRootRefusalFastPath(t *testing.T) { + for _, tok := range []string{"auto", "yolo"} { + cfg, err := parseFlags([]string{"--permission-mode", tok}) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + eff := app.ResolveAuthoritativePosture(posturePreCheckConfig(cfg, port.NopDiagnostics{})) + if err := app.PostureRefusalReason(eff, true); err == nil { + t.Fatalf("--permission-mode %s as unsandboxed root was not refused on the fast path (posture %s)", tok, eff) + } + } + yolo, err := parseFlags([]string{"--yolo"}) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + if err := app.PostureRefusalReason(app.ResolveAuthoritativePosture(posturePreCheckConfig(yolo, port.NopDiagnostics{})), true); err == nil { + t.Fatal("--yolo as unsandboxed root was not refused on the fast path") + } +} + +func TestADR_0365_PermissionModeHelpNamesBothHalvesAndEveryToken(t *testing.T) { + for _, want := range append(app.PermissionModeNames(), "process-wide", "new sessions") { + if !strings.Contains(permissionModeHelp, want) { + t.Fatalf("--permission-mode help lacks %q: %s", want, permissionModeHelp) + } + } +} diff --git a/cmd/mecatequi/flags.go b/cmd/mecatequi/flags.go index 60c4d3bd1b..77ba45be74 100644 --- a/cmd/mecatequi/flags.go +++ b/cmd/mecatequi/flags.go @@ -143,6 +143,10 @@ type flags struct { // explicit --posture so composition lets CLI out-rank the settings.yaml key. posture string postureFlagSet bool + // permissionMode is the raw --permission-mode token (ADR 0365), validated at + // parse time; permissionModeFlagSet records it was passed explicitly. + permissionMode string + permissionModeFlagSet bool // Reasoning-effort tier. reasoningEffortFlagSet records an explicit // --reasoning-effort so composition lets CLI out-rank the settings.yaml key. reasoningEffort string @@ -207,6 +211,8 @@ func parseFlags(argv []string) (flags, error) { switch fl.Name { case "posture": f.postureFlagSet = true + case "permission-mode": + f.permissionModeFlagSet = true case "shell": f.shellFlagSet = true case "subagent-model-router": @@ -228,6 +234,9 @@ func parseFlags(argv []string) (flags, error) { f.defaultProviderFlagSet = true } }) + if err := validatePermissionModeFlags(f); err != nil { + return flags{}, err + } resolvedShell, err := cliconfig.ResolveCommandRunnerConfig(f.shell, f.shellFlagSet, true, f.permissionConfigs) if err != nil { return flags{}, fmt.Errorf("command runner configuration: %w", err) @@ -331,12 +340,13 @@ func configureFlags(fs *flag.FlagSet, f *flags) { fs.StringVar(&f.guardrailsModel, "guardrails-model", "", "Model identifier or alias for the tool-free guardrails checker. Setting this flag enables guardrails unless --guardrails=off. A guardrail model slot takes precedence. Default: empty.") fs.StringVar(&f.guardrailsMode, "guardrails", "", "Set to off to disable guardrails, including configured checker models. Other values leave guardrails controlled by the configured checker model.") - fs.StringVar(&f.subagentAskReviewer, "subagent-ask-reviewer", "", "Model identifier or alias for the tool-free reviewer of child permission requests in headless runs. Default: empty, which disables the reviewer.") + fs.StringVar(&f.subagentAskReviewer, "subagent-ask-reviewer", "", "Model identifier or alias for the tool-free reviewer of child permission requests in headless runs. Default: empty, which leaves the reviewer off except in a headless auto or yolo permission mode, where it is on by default (ask-reviewer model slot, else the session model). Set off to disable it explicitly.") fs.BoolVar(&f.subagentModelRouter, "subagent-model-router", false, "Set false to disable configured subagent model routing. A configured models.router taxonomy enables routing; this flag does not enable it.") fs.IntVar(&f.subagentAskReviewerMaxDenies, "subagent-ask-reviewer-max-denies", agent.DefaultAskReviewMaxDenies, "Consecutive non-allow reviewer outcomes before the reviewer is disabled for the rest of the run. Values less than or equal to 0 use the default: 3.") fs.StringVar(&f.subagentAskReviewerPolicyFile, "subagent-ask-reviewer-policy", "", "Trusted policy rubric file for --subagent-ask-reviewer. Its contents replace the built-in rubric. An unreadable file fails startup.") - fs.StringVar(&f.posture, "posture", "", "Permission posture: strict (default), trusted, auto, or yolo. Headless runs need an explicit trust source such as --trust-project to admit project content. Deny and configured ask rules still apply. Unknown values use strict.") + fs.StringVar(&f.permissionMode, "permission-mode", "", permissionModeHelp) + fs.StringVar(&f.posture, "posture", "", "DEPRECATED: use --permission-mode. Permission posture: strict (default), trusted, auto, or yolo. Headless runs need an explicit trust source such as --trust-project to admit project content. Deny and configured ask rules still apply. Unknown values use strict.") fs.StringVar(&f.reasoningEffort, "reasoning-effort", "", "Reasoning effort: auto, low, medium, high, xhigh, or max. Empty uses the provider or operator setting. OpenAI maps xhigh and max to high. Unknown values use the provider or operator setting.") fs.BoolVar(&f.trustProject, "trust-project", false, "Allow workspace content to provide project instructions, rules, agents, skills, souls, commands, Git snapshots, and the read-only child worktree shell. Default: false. Enable only for a repository and Git metadata you trust.") @@ -478,6 +488,10 @@ func appConfig(f flags, diag port.Diagnostics, obs observability) app.Config { Posture: app.ParsePosture(f.posture), PostureFlagSet: f.postureFlagSet, + // Permission mode (ADR 0365): an explicit token out-ranks the deprecated + // --posture in app.Build's foldPermissionMode. + PermissionMode: f.permissionMode, + PermissionModeFlagSet: f.permissionModeFlagSet, // Explicit workspace trust: on this HEADLESS root the posture ladder never // raises TrustProject, so --trust-project is the one-shot opt-in that admits // both project steering and the read-only worktree shell. diff --git a/cmd/mecatequi/main.go b/cmd/mecatequi/main.go index c2a27e9994..a353ae5afd 100644 --- a/cmd/mecatequi/main.go +++ b/cmd/mecatequi/main.go @@ -24,7 +24,7 @@ // (strict), the main engine asks on every mutate — so a strict + headless run that // reaches a mutate is CANCELLED on that ask (run.Cancel, drain-to-close) and exits 1 // with an actionable "no approver" message naming the fix. The intended CI posture is -// therefore --posture auto (allow-all, child injection-defense ON) or trusted/yolo, +// therefore --permission-mode auto (allow-all, child injection-defense ON) or trusted/yolo, // where the main engine does not ask. --timeout is the orthogonal wall-clock backstop. // See run()'s cancel-on-ask path and flags.posture. package main @@ -69,6 +69,7 @@ func realMain(argv []string, stdout, stderr io.Writer) int { } emitAuthFileWarning(stderr, f.providerCredentials.AuthFileWarning) diag := newDiagnostics() + warnDeprecatedPermissionFlags(diag, f) // Observability (issue #343): OPT-IN OTLP push. Built right after // flag parse so the flush-on-exit defer covers EVERY exit path (setup-failure @@ -188,7 +189,8 @@ func verdictLine(sum Summary, noApprover, timedOut bool) string { return fmt.Sprintf("mecatequi: TIMED OUT — stop=%s, %s; the run exceeded --timeout and was cancelled", stop, files) case noApprover: return "mecatequi: NO APPROVER — a permission approval was requested but none is attached (--headless); " + - "re-run with --posture auto|trusted|yolo or add allow rules. stop=" + stop + "re-run with --permission-mode auto|yolo (plus --guardrails-model or --guardrails off), " + + "or add allow rules (--permission-mode trusted --trust-project honours the repo's). stop=" + stop default: return fmt.Sprintf("mecatequi: done — stop=%s, %s", stop, files) } diff --git a/cmd/mecatequi/permission_mode.go b/cmd/mecatequi/permission_mode.go new file mode 100644 index 0000000000..5a9d1867d6 --- /dev/null +++ b/cmd/mecatequi/permission_mode.go @@ -0,0 +1,51 @@ +package main + +import ( + "context" + "fmt" + "strings" + + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/app" +) + +// permissionModeHelp is the --permission-mode usage line (ADR 0365). It names +// both halves a token sets and their lifetimes, and lists every valid token from +// the composition table so help and parsing cannot drift. +var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + + ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; trusted for trusted and trusted-accept-edits; auto; yolo), " + + "and the session mode the run's session starts in. Default: default. " + + "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model or the guardrail model slot) or an explicit --guardrails off. " + + "trusted and trusted-accept-edits need a trust source such as --trust-project on this headless root. " + + "Deny and configured ask rules still apply. Replaces the deprecated --posture; --trust-project still combines with it." + +// validatePermissionModeFlags fails fast on an unknown --permission-mode token +// and on a --permission-mode combined with the deprecated --posture alias. +func validatePermissionModeFlags(f flags) error { + if !f.permissionModeFlagSet { + return nil + } + if _, err := app.ParsePermissionMode(f.permissionMode); err != nil { + return fmt.Errorf("--permission-mode: %w", err) + } + if f.postureFlagSet { + return fmt.Errorf("--permission-mode and --posture are both set: pass only --permission-mode (--posture is its deprecated alias)") + } + return nil +} + +// warnDeprecatedPermissionFlags emits exactly one deprecation WARN when the +// operator passed the deprecated --posture explicitly. +func warnDeprecatedPermissionFlags(diag port.Diagnostics, f flags) { + if diag == nil || !f.postureFlagSet { + return + } + replacement := "default" + if tok, ok := app.PermissionModeForPair(app.ParsePosture(f.posture), session.ModeDefault); ok { + replacement = tok.Name + } + diag.Log(context.Background(), port.LevelWarn, + "--posture is DEPRECATED; use --permission-mode instead (ADR 0365)", + "posture", f.posture, "replacement", "--permission-mode "+replacement) +} diff --git a/cmd/mecatequi/permission_mode_test.go b/cmd/mecatequi/permission_mode_test.go new file mode 100644 index 0000000000..a0d6e9e763 --- /dev/null +++ b/cmd/mecatequi/permission_mode_test.go @@ -0,0 +1,282 @@ +package main + +import ( + "bytes" + "fmt" + "log/slog" + "os" + "os/exec" + "path/filepath" + "regexp" + "slices" + "strings" + "testing" + + "sigs.k8s.io/yaml" + + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/internal/adapter/slogdiag" + "github.com/stacklok/mecatl/internal/app" +) + +func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { + for _, tc := range []struct{ posture, token string }{ + {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, + } { + t.Run(tc.posture, func(t *testing.T) { + alias, err := parseFlags([]string{"--prompt", "x", "--posture", tc.posture}) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + ac := appConfig(alias, port.NopDiagnostics{}, observability{}) + tok, err := app.ParsePermissionMode(tc.token) + if err != nil { + t.Fatal(err) + } + if got := app.ResolveAuthoritativePosture(ac); got != tok.Posture || ac.DefaultSessionMode != "" { + t.Fatalf("--posture %s = (%s, %q), want the %q token's (%s, default)", tc.posture, got, ac.DefaultSessionMode, tc.token, tok.Posture) + } + var buf bytes.Buffer + warnDeprecatedPermissionFlags(slogdiag.NewFromLogger(slog.New(slog.NewTextHandler(&buf, nil))), alias) + if n := strings.Count(buf.String(), "DEPRECATED"); n != 1 || !strings.Contains(buf.String(), "--permission-mode "+tc.token) { + t.Fatalf("--posture %s logged %d deprecation WARNs, want exactly one naming --permission-mode %s: %s", tc.posture, n, tc.token, buf.String()) + } + }) + } + f, err := parseFlags([]string{"--prompt", "x", "--permission-mode", "auto"}) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + var buf bytes.Buffer + warnDeprecatedPermissionFlags(slogdiag.NewFromLogger(slog.New(slog.NewTextHandler(&buf, nil))), f) + if buf.Len() != 0 { + t.Fatalf("--permission-mode emitted a deprecation WARN: %s", buf.String()) + } + if ac := appConfig(f, port.NopDiagnostics{}, observability{}); !ac.PermissionModeFlagSet || ac.PermissionMode != "auto" { + t.Fatalf("appConfig did not carry --permission-mode: set=%v mode=%q", ac.PermissionModeFlagSet, ac.PermissionMode) + } +} + +func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { + _, err := parseFlags([]string{"--prompt", "x", "--permission-mode", "auto", "--posture", "auto"}) + if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { + t.Fatalf("--permission-mode with --posture err = %v, want a pass-one startup error", err) + } + _, err = parseFlags([]string{"--prompt", "x", "--permission-mode", "bogus"}) + if err == nil { + t.Fatal("unknown --permission-mode token parsed without error") + } + for _, name := range app.PermissionModeNames() { + if !strings.Contains(err.Error(), name) || !strings.Contains(permissionModeHelp, name) { + t.Fatalf("unknown-token error %q or help does not name %q", err, name) + } + } + if !strings.Contains(permissionModeHelp, "process-wide") { + t.Fatal("--permission-mode help does not say which half is process-wide") + } +} + +// actionFile is the subset of the composite action.yml the checker-choice test reads. +type actionFile struct { + Inputs map[string]struct { + Default string `json:"default"` + } `json:"inputs"` + Runs struct { + Steps []struct { + Name string `json:"name"` + Env map[string]string `json:"env"` + Run string `json:"run"` + } `json:"steps"` + } `json:"runs"` +} + +type workflowFile struct { + Jobs map[string]struct { + Steps []struct { + Uses string `json:"uses"` + With map[string]any `json:"with"` + } `json:"steps"` + } `json:"jobs"` +} + +var inputRef = regexp.MustCompile(`^\$\{\{\s*inputs\.([a-z0-9-]+)\s*\}\}$`) + +// runActionScript executes the action's real "Run mecatequi" bash body with +// the given inputs (defaults fill the rest) against a fake binary that records +// its argv, and returns that argv plus the script's combined output. +func runActionScript(t *testing.T, action actionFile, with map[string]string) ([]string, string, error) { + t.Helper() + idx := slices.IndexFunc(action.Runs.Steps, func(s struct { + Name string `json:"name"` + Env map[string]string `json:"env"` + Run string `json:"run"` + }) bool { + return s.Name == "Run mecatequi" + }) + if idx < 0 { + t.Fatal("action.yml has no \"Run mecatequi\" step") + } + step := action.Runs.Steps[idx] + dir := t.TempDir() + argsOut := filepath.Join(dir, "argv") + fake := "#!/bin/sh\nprintf '%s\\n' \"$@\" > \"$ARGS_OUT\"\n" + if err := os.WriteFile(filepath.Join(dir, "mecatequi"), []byte(fake), 0o700); err != nil { + t.Fatal(err) + } + prompt := filepath.Join(dir, "prompt.md") + if err := os.WriteFile(prompt, []byte("task"), 0o600); err != nil { + t.Fatal(err) + } + overrides := map[string]string{ + "prompt-file": prompt, + "workspace": dir, + "out-diff": filepath.Join(dir, "p.patch"), + "out-summary": filepath.Join(dir, "s.json"), + "out-events": filepath.Join(dir, "e.jsonl"), + } + for k, v := range with { + overrides[k] = v + } + env := []string{ + "PATH=" + os.Getenv("PATH"), + "HOME=" + dir, + "RUNNER_TEMP=" + dir, + "GITHUB_OUTPUT=" + filepath.Join(dir, "github_output"), + "ARGS_OUT=" + argsOut, + } + for name, expr := range step.Env { + m := inputRef.FindStringSubmatch(expr) + if m == nil { + t.Fatalf("step env %s=%q is not an inputs reference", name, expr) + } + input, ok := action.Inputs[m[1]] + if !ok { + t.Fatalf("step env %s references undeclared input %q", name, m[1]) + } + value := input.Default + if v, ok := overrides[m[1]]; ok { + value = v + } + env = append(env, name+"="+value) + } + cmd := exec.Command("bash", "-c", step.Run) + cmd.Env = env + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + return nil, string(out), err + } + raw, rerr := os.ReadFile(argsOut) + if rerr != nil { + t.Fatalf("fake mecatequi was not invoked: %v\n%s", rerr, out) + } + return strings.Split(strings.TrimRight(string(raw), "\n"), "\n"), string(out), nil +} + +// hasPair reports whether argv carries flag immediately followed by value. +func hasPair(argv []string, flag, value string) bool { + for i := 0; i+1 < len(argv); i++ { + if argv[i] == flag && argv[i+1] == value { + return true + } + } + return false +} + +// TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0365 AC2.3 +// for the composite action and this repo's live workflow: whenever they run an +// allow-all mode they pass a checker model or the explicit --guardrails off, so +// the startup refusal never fires on a shipped default. It executes the action's +// real bash body against a fake binary rather than grepping it. +func TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { + if _, err := exec.LookPath("bash"); err != nil { + t.Skip("bash is required to execute the composite action body") + } + raw, err := os.ReadFile("../../.github/actions/mecatequi/action.yml") + if err != nil { + t.Fatal(err) + } + var action actionFile + if err := yaml.Unmarshal(raw, &action); err != nil { + t.Fatalf("parse action.yml: %v", err) + } + + t.Run("action defaults", func(t *testing.T) { + argv, out, err := runActionScript(t, action, nil) + if err != nil { + t.Fatalf("action body failed: %v\n%s", err, out) + } + if !hasPair(argv, "--permission-mode", "auto") || !hasPair(argv, "--guardrails", "off") || slices.Contains(argv, "--posture") { + t.Fatalf("default action argv = %q, want --permission-mode auto with --guardrails off and no --posture", argv) + } + }) + t.Run("checker model", func(t *testing.T) { + argv, out, err := runActionScript(t, action, map[string]string{"guardrails-model": "checker-model"}) + if err != nil { + t.Fatalf("action body failed: %v\n%s", err, out) + } + if !hasPair(argv, "--guardrails-model", "checker-model") || slices.Contains(argv, "--guardrails") { + t.Fatalf("argv = %q, want --guardrails-model checker-model and no kill-switch", argv) + } + }) + t.Run("deprecated posture input", func(t *testing.T) { + argv, out, err := runActionScript(t, action, map[string]string{"posture": "auto"}) + if err != nil { + t.Fatalf("action body failed: %v\n%s", err, out) + } + if !hasPair(argv, "--posture", "auto") || slices.Contains(argv, "--permission-mode") || !hasPair(argv, "--guardrails", "off") { + t.Fatalf("argv = %q, want the deprecated --posture auto alone with --guardrails off", argv) + } + if !strings.Contains(out, "::warning::") || !strings.Contains(out, "permission-mode") { + t.Fatalf("deprecated posture input did not warn naming permission-mode: %s", out) + } + }) + t.Run("both inputs fail", func(t *testing.T) { + _, out, err := runActionScript(t, action, map[string]string{"posture": "auto", "permission-mode": "auto"}) + if err == nil || !strings.Contains(out, "pass only permission-mode") { + t.Fatalf("both inputs err = %v, want a failed step naming permission-mode: %s", err, out) + } + }) + + t.Run("live workflow", func(t *testing.T) { + raw, err := os.ReadFile("../../.github/workflows/mecatequi.yml") + if err != nil { + t.Fatal(err) + } + var wf workflowFile + if err := yaml.Unmarshal(raw, &wf); err != nil { + t.Fatalf("parse mecatequi.yml: %v", err) + } + found := 0 + for _, job := range wf.Jobs { + for _, step := range job.Steps { + if step.Uses != "./.github/actions/mecatequi" { + continue + } + found++ + if _, ok := step.With["posture"]; ok { + t.Fatalf("workflow still passes the deprecated posture input: %v", step.With) + } + with := map[string]string{} + for _, k := range []string{"permission-mode", "guardrails-model", "subagent-ask-reviewer"} { + if v, ok := step.With[k]; ok { + with[k] = fmt.Sprint(v) + } + } + argv, out, err := runActionScript(t, action, with) + if err != nil { + t.Fatalf("workflow inputs failed the action body: %v\n%s", err, out) + } + if !hasPair(argv, "--permission-mode", "auto") { + t.Fatalf("workflow argv = %q, want --permission-mode auto", argv) + } + if !hasPair(argv, "--guardrails", "off") && !slices.Contains(argv, "--guardrails-model") { + t.Fatalf("workflow runs allow-all without a checker choice: %q", argv) + } + } + } + if found == 0 { + t.Fatal("mecatequi.yml does not use ./.github/actions/mecatequi") + } + }) +} diff --git a/cmd/mecatequi/run.go b/cmd/mecatequi/run.go index 3365f995d5..15f134950f 100644 --- a/cmd/mecatequi/run.go +++ b/cmd/mecatequi/run.go @@ -118,7 +118,7 @@ type SummaryUsage struct { // runOutcome is the result of run(): the Summary, the captured event stream (the // durable-log source), and NoApprover — set when the run was cancelled because the MAIN // engine asked for a permission approval and mecatequi has no approver attached. The -// caller uses NoApprover to print the actionable "re-run with --posture …" guidance and +// caller uses NoApprover to print the actionable "re-run with --permission-mode …" guidance and // to distinguish a no-approver cancel from an ordinary cancel in the operator message // (the StopReason is "cancelled" in both, honestly). type runOutcome struct { diff --git a/deploy/helm/mecak8s/chart_test.go b/deploy/helm/mecak8s/chart_test.go index 18dc9d9433..e6ca71f601 100644 --- a/deploy/helm/mecak8s/chart_test.go +++ b/deploy/helm/mecak8s/chart_test.go @@ -923,7 +923,8 @@ func TestMecak8sHelmChart_DeployCheckProductionFixtureRuntimeAndSpread(t *testin "--redis-max-followers=32", "--session-lease-k8s-namespace=default", "--headless=true", - "--posture=auto", + "--permission-mode=auto", + "--guardrails=off", "--default-provider=openrouter", "--model=anthropic/claude-sonnet-4-6", "--max-run-tokens=200000", @@ -3072,3 +3073,45 @@ mcp: t.Fatalf("OAuth profile checksums = %q and %q; profile change must roll pods", firstSum, secondSum) } } + +// TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0365 AC2.3 for +// the chart: it runs mecak8s in the allow-all auto permission mode, and mecak8s +// refuses that mode without a checker, so every render must declare the checker +// choice. An empty guardrails.model is the explicit unsupervised --guardrails=off; +// a set model becomes --guardrails-model and never carries the kill-switch. +func TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { + cases := []struct { + name string + extra []string + want string + notWant string + }{ + {name: "default declares unsupervised", want: "--guardrails=off", notWant: "--guardrails-model="}, + {name: "model declares checker", extra: []string{"--set-string", "guardrails.model=openrouter/checker"}, want: "--guardrails-model=openrouter/checker", notWant: "--guardrails=off"}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + rendered, err := helm(t, append(secureProductionArgs(), tc.extra...)...) + if err != nil { + t.Fatalf("render: %v\n%s", err, rendered) + } + args := deploymentFromRender(t, rendered).Spec.Template.Spec.Containers[0].Args + if !slices.Contains(args, "--permission-mode=auto") { + t.Fatalf("args lack --permission-mode=auto: %q", args) + } + for _, a := range args { + if strings.HasPrefix(a, "--posture") || a == "--yolo" { + t.Fatalf("args still use deprecated alias %q: %q", a, args) + } + } + if !slices.Contains(args, tc.want) { + t.Fatalf("args lack checker choice %q: %q", tc.want, args) + } + for _, a := range args { + if strings.HasPrefix(a, tc.notWant) { + t.Fatalf("args carry conflicting %q: %q", a, args) + } + } + }) + } +} diff --git a/deploy/helm/mecak8s/templates/deployment.yaml b/deploy/helm/mecak8s/templates/deployment.yaml index b7c5ae9d1d..1ce2dbac85 100644 --- a/deploy/helm/mecak8s/templates/deployment.yaml +++ b/deploy/helm/mecak8s/templates/deployment.yaml @@ -111,7 +111,12 @@ spec: {{- end }} - {{ printf "--session-lease-k8s-namespace=%s" .Release.Namespace | quote }} - --headless=true - - --posture=auto + - --permission-mode=auto + {{- if .Values.guardrails.model }} + - {{ printf "--guardrails-model=%s" .Values.guardrails.model | quote }} + {{- else }} + - --guardrails=off + {{- end }} {{- if .Values.logging.level }} - {{ printf "--log-level=%s" .Values.logging.level | quote }} {{- end }} diff --git a/deploy/helm/mecak8s/values.schema.json b/deploy/helm/mecak8s/values.schema.json index aff20c8435..f4fa71530e 100644 --- a/deploy/helm/mecak8s/values.schema.json +++ b/deploy/helm/mecak8s/values.schema.json @@ -92,6 +92,20 @@ }, "maxRunTokens": {"type": ["integer", "null"], "minimum": 1}, "maxTeamTokens": {"type": ["integer", "null"], "minimum": 1}, + "guardrails": { + "type": "object", + "additionalProperties": false, + "required": ["model"], + "properties": { + "model": { + "type": "string", + "anyOf": [ + {"const": ""}, + {"pattern": "^\\S(?:.*\\S)?$"} + ] + } + } + }, "telemetry": { "type": "object", "additionalProperties": false, diff --git a/deploy/helm/mecak8s/values.yaml b/deploy/helm/mecak8s/values.yaml index e7bd132089..eb786e54e3 100644 --- a/deploy/helm/mecak8s/values.yaml +++ b/deploy/helm/mecak8s/values.yaml @@ -110,6 +110,20 @@ model: "" maxRunTokens: null maxTeamTokens: null +# guardrails declares the checker choice for the chart's allow-all permission +# mode (--permission-mode=auto: every tool runs without asking, only deny rules +# and configured ask rules still apply). mecak8s refuses to start an allow-all +# mode without a checker unless the operator opts out explicitly, so the chart +# always passes one of two flags: +# - model set: --guardrails-model=, a tool-free checker model that +# inspects outbound tool arguments and inbound results. +# - model empty (the default): --guardrails=off, a DELIBERATE choice to run +# unsupervised, with no checker inspecting tool content. The kill-switch also +# disables a guardrail model slot bound in mounted settings, so set model here +# to the checker you want rather than relying on a slot. +guardrails: + model: "" + # Stable, non-secret identity exported on mecak8s OTel resources. Empty is safe # only for live Helm install/upgrade: Helm creates a UUID on install and preserves # the live ConfigMap value on ordinary upgrades. Offline/template-based GitOps must From fdd8995905a3cc7916aab2417d2bd9ab96c5cee9 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:44:20 +0300 Subject: [PATCH 04/48] fix(permissions): let gRPC CreateSession use the server default mode The gRPC create path collapsed an UNSPECIFIED mode to default before the service could apply server.Config.DefaultMode, so the session half of a permission-mode token never reached gRPC clients. Keep it empty on create, as the HTTP path already did; SetMode is unchanged. Model the operator-tier permissionMode: key in the generated configuration reference and mark posture: deprecated there. Co-Authored-By: Claude Opus 5.5 (1M context) --- contracts/gen/go/mecatl/v1/harness.pb.go | 4 +- contracts/proto/mecatl/v1/harness.proto | 4 +- internal/adapter/server/default_mode_test.go | 66 ++++++++++++++++++++ internal/adapter/server/grpc.go | 2 +- internal/adapter/server/mapper.go | 11 ++++ internal/configgen/build.go | 26 +++++++- internal/configgen/configgen_test.go | 3 + internal/configgen/settings.skeleton.yaml | 17 ++++- user-docs/reference/configuration.md | 12 +++- user-docs/reference/grpc-api.md | 8 +-- 10 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 internal/adapter/server/default_mode_test.go diff --git a/contracts/gen/go/mecatl/v1/harness.pb.go b/contracts/gen/go/mecatl/v1/harness.pb.go index d1132ad15d..f705e0a2d4 100644 --- a/contracts/gen/go/mecatl/v1/harness.pb.go +++ b/contracts/gen/go/mecatl/v1/harness.pb.go @@ -999,7 +999,9 @@ func (x *Limits) GetMaxConsecutiveFailures() int32 { // CreateSessionRequest opens a new session. type CreateSessionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - // mode is the permission posture; unspecified defaults to DEFAULT. + // mode is the permission posture; unspecified uses the server's configured + // default session mode, which is DEFAULT unless the operator chose a + // permission mode that starts sessions elsewhere. Mode PermissionMode `protobuf:"varint,2,opt,name=mode,proto3,enum=mecatl.v1.PermissionMode" json:"mode,omitempty"` // limits are the optional stop conditions. Limits *Limits `protobuf:"bytes,3,opt,name=limits,proto3" json:"limits,omitempty"` diff --git a/contracts/proto/mecatl/v1/harness.proto b/contracts/proto/mecatl/v1/harness.proto index 1f4c74c36e..02d4069a44 100644 --- a/contracts/proto/mecatl/v1/harness.proto +++ b/contracts/proto/mecatl/v1/harness.proto @@ -540,7 +540,9 @@ message Limits { message CreateSessionRequest { reserved 1, 8; reserved "workspace", "source_session_id"; - // mode is the permission posture; unspecified defaults to DEFAULT. + // mode is the permission posture; unspecified uses the server's configured + // default session mode, which is DEFAULT unless the operator chose a + // permission mode that starts sessions elsewhere. PermissionMode mode = 2; // limits are the optional stop conditions. Limits limits = 3; diff --git a/internal/adapter/server/default_mode_test.go b/internal/adapter/server/default_mode_test.go new file mode 100644 index 0000000000..e9b42466b4 --- /dev/null +++ b/internal/adapter/server/default_mode_test.go @@ -0,0 +1,66 @@ +package server_test + +import ( + "context" + "testing" + "time" + + 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/session" + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +// TestGRPCCreateSessionUnspecifiedModeUsesServerDefault pins that a gRPC +// CreateSession leaving mode UNSPECIFIED starts in the server's configured +// DefaultMode (the session half of the operator's permission mode, ADR 0365), +// while an explicit mode still wins. +func TestGRPCCreateSessionUnspecifiedModeUsesServerDefault(t *testing.T) { + llm := mockllm.New() + svc, err := newPlacementTeamTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{ + LLM: llm, + Catalog: tool.NewCatalog(), + Policy: permpolicy.NewPolicy(allowRules(), nil), + Model: "test-model", + }), + Store: memstore.New(), + PlacementProvider: testPlacementProvider{}, + PlacementScope: "test", + Now: func() time.Time { return time.Unix(0, 0) }, + DefaultCapabilities: llm.Capabilities(), + DefaultMode: session.ModePlan, + }) + if err != nil { + t.Fatalf("new service: %v", err) + } + client, cleanup := dialGRPC(t, svc) + defer cleanup() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + for _, tc := range []struct { + req mecatlv1.PermissionMode + want session.PermissionMode + }{ + {mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED, session.ModePlan}, + {mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT, session.ModeDefault}, + {mecatlv1.PermissionMode_PERMISSION_MODE_ACCEPT_EDITS, session.ModeAccept}, + } { + cs, err := client.CreateSession(ctx, &mecatlv1.CreateSessionRequest{Mode: tc.req}) + if err != nil { + t.Fatalf("CreateSession(%s): %v", tc.req, err) + } + sess, err := svc.GetSession(ctx, session.SessionID(cs.GetSessionId())) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if sess.Mode != tc.want { + t.Errorf("CreateSession(%s) started in %q, want %q", tc.req, sess.Mode, tc.want) + } + } +} diff --git a/internal/adapter/server/grpc.go b/internal/adapter/server/grpc.go index 3e6557182a..a2ec1a9c16 100644 --- a/internal/adapter/server/grpc.go +++ b/internal/adapter/server/grpc.go @@ -116,7 +116,7 @@ func (h *HarnessServer) CreateSession(ctx context.Context, req *mecatlv1.CreateS if !grant.IsEmpty() { opts = append(opts, WithClientMCP(grant)) } - sess, err := h.svc.CreateSessionWithProfile(ctx, modeFromProto(req.GetMode()), limitsFromProto(req.GetLimits()), sel, profile, opts...) + sess, err := h.svc.CreateSessionWithProfile(ctx, createModeFromProto(req.GetMode()), limitsFromProto(req.GetLimits()), sel, profile, opts...) if err != nil { return nil, toStatus(err) } diff --git a/internal/adapter/server/mapper.go b/internal/adapter/server/mapper.go index 402e3597df..92c5686044 100644 --- a/internal/adapter/server/mapper.go +++ b/internal/adapter/server/mapper.go @@ -1405,6 +1405,17 @@ func modeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { } } +// createModeFromProto maps a CreateSession mode. Unlike modeFromProto, an +// UNSPECIFIED mode stays empty so Service.createSession applies the server's +// configured DefaultMode (the session half of the operator's permission mode, +// ADR 0365), matching the HTTP create path. +func createModeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { + if m == mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { + return "" + } + return modeFromProto(m) +} + func guardrailApprovalKindFromProto(kind mecatlv1.GuardrailApprovalKind) session.GuardrailApprovalKind { switch kind { case mecatlv1.GuardrailApprovalKind_GUARDRAIL_APPROVAL_KIND_ACTION: diff --git a/internal/configgen/build.go b/internal/configgen/build.go index a25a73d8e9..9c17f1bbc3 100644 --- a/internal/configgen/build.go +++ b/internal/configgen/build.go @@ -29,6 +29,7 @@ func BuildModel(docs Docs) *Model { return &Model{Subtrees: []*Subtree{ permissionsSubtree(docs), guardrailsSubtree(docs), + permissionModeSubtree(docs), postureSubtree(docs), reasoningEffortSubtree(docs), planModeAutoApproveSubtree(docs), @@ -398,11 +399,34 @@ func learningSubtree(docs Docs) *Subtree { } } +func permissionModeSubtree(docs Docs) *Subtree { + return &Subtree{ + Key: "permissionMode", + Tier: TierOperator, + Doc: "OPERATOR-TIER named permission mode (ADR 0365): plan, default, accept-edits, trusted, " + + "trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, " + + "fixed at startup, and the mode new sessions start in, which each session may change. auto " + + "and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. " + + "An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: " + + "key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default.", + CommentedOut: true, + Scalar: true, + Fields: []*Field{{ + Key: "permissionMode", + Type: "string", + Default: "(empty)", + Doc: docFor(docs, "Config.PermissionMode", "the named permission-mode token"), + ExampleValue: "trusted-accept-edits", + }}, + } +} + func postureSubtree(docs Docs) *Subtree { return &Subtree{ Key: "posture", Tier: TierOperator, - Doc: "OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated " + + Doc: "DEPRECATED: use permissionMode: instead (ADR 0365); still honoured with a WARN for one release. " + + "OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated " + "trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project " + "cannot raise the automation posture). Empty = keep the CLI/default.", CommentedOut: true, diff --git a/internal/configgen/configgen_test.go b/internal/configgen/configgen_test.go index dad6914e64..129c4e7036 100644 --- a/internal/configgen/configgen_test.go +++ b/internal/configgen/configgen_test.go @@ -110,6 +110,8 @@ func authoritativeKeys() []string { collect("mcp.servers.auth.oauth.tools", permconfig.MCPStaticToolProfile{}) // posture is a bare scalar Config field, not a *Section. keys = append(keys, "posture") + // permissionMode is likewise a bare scalar Config field (ADR 0365). + keys = append(keys, "permissionMode") // output-economy is absent: the setting was REMOVED (a // clean break) and MUST NOT appear in generated artifacts (pinned by // TestDeprecatedOutputEconomyIsAbsentFromGeneratedArtifacts). @@ -366,6 +368,7 @@ func TestSubtreeTiersAreAsPinned(t *testing.T) { "permissions": configgen.TierProject, // allow/ask/deny + subagent: project-settable (allows trust-gated) "guardrails": configgen.TierOperator, // operator-only: a project cannot weaken a security checker "posture": configgen.TierOperator, // operator-only: a project cannot raise the automation posture + "permissionMode": configgen.TierOperator, // operator-only: a project cannot choose its own permission mode (ADR 0365) "reasoning-effort": configgen.TierOperator, // operator-only: a project cannot raise the model's reasoning spend "plan-mode-auto-approve": configgen.TierOperator, // operator-only: a project cannot grant an autonomous approval capability (issue #206) "providers": configgen.TierOperator, // operator-only: a project cannot choose LLM endpoints or auth posture diff --git a/internal/configgen/settings.skeleton.yaml b/internal/configgen/settings.skeleton.yaml index edcae4b61b..00cb59f1ba 100644 --- a/internal/configgen/settings.skeleton.yaml +++ b/internal/configgen/settings.skeleton.yaml @@ -96,10 +96,21 @@ # prompt: "" # failClosed: false +#| === permissionMode === (tier: operator) +#| OPERATOR-TIER named permission mode (ADR 0365): plan, default, accept-edits, trusted, +#| trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide +#| posture, fixed at startup, and the mode new sessions start in, which each session may +#| change. auto and yolo refuse to start without a guardrails checker unless guardrails +#| are explicitly off. An explicit --permission-mode out-ranks this key, and it +#| out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with +#| a WARN. Empty = keep the CLI/default. +# permissionMode: trusted-accept-edits + #| === posture === (tier: operator) -#| OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated -#| trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project -#| cannot raise the automation posture). Empty = keep the CLI/default. +#| DEPRECATED: use permissionMode: instead (ADR 0365); still honoured with a WARN for +#| one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the +#| graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a +#| project cannot raise the automation posture). Empty = keep the CLI/default. # posture: trusted #| === reasoning-effort === (tier: operator) diff --git a/user-docs/reference/configuration.md b/user-docs/reference/configuration.md index 2038f1a5aa..e2d2a4d80a 100644 --- a/user-docs/reference/configuration.md +++ b/user-docs/reference/configuration.md @@ -74,11 +74,21 @@ OPERATOR-TIER LLM content-checker (issue #27). Parsed strictly. A project-tier g | `guardrails.rules[].prompt` | `string` | `(empty)` | Prompt adds operator task-risk context beneath the fixed harness safety, provenance, evidence, and structured-output rubric; it cannot replace it. | | `guardrails.rules[].failClosed` | `bool` | `false` | FailClosed optionally overrides the fail-closed global default for this rule. | +## `permissionMode` + +Tier: **operator** + +OPERATOR-TIER named permission mode (ADR 0365): plan, default, accept-edits, trusted, trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, fixed at startup, and the mode new sessions start in, which each session may change. auto and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. + +| Value | Type | Default | Description | +| --- | --- | --- | --- | +| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0365: plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets the posture and the default session mode together and supersedes the deprecated posture: key. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | + ## `posture` Tier: **operator** -OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project cannot raise the automation posture). Empty = keep the CLI/default. +DEPRECATED: use permissionMode: instead (ADR 0365); still honoured with a WARN for one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project cannot raise the automation posture). Empty = keep the CLI/default. | Value | Type | Default | Description | | --- | --- | --- | --- | diff --git a/user-docs/reference/grpc-api.md b/user-docs/reference/grpc-api.md index 5767747a83..58a0b4a848 100644 --- a/user-docs/reference/grpc-api.md +++ b/user-docs/reference/grpc-api.md @@ -672,10 +672,10 @@ data into the model or dedicated session debugger. ### Client controls and posture -The embedded server accepts `--yolo` with the same allow-all semantics, -root-user refusal, and `MECATL_SANDBOX`/`IS_SANDBOX` environment checks as -`mecated`. Connect mode rejects `--yolo` because the external server owns its -posture. See +The embedded server accepts `--permission-mode` with the same modes, checker +requirement, root-user refusal, and `MECATL_SANDBOX`/`IS_SANDBOX` environment +checks as `mecated`. Connect mode accepts only `plan`, `default`, and +`accept-edits` because the external server owns its posture. See [Permissions and posture](/features/security-and-execution/permissions-and-posture.md). Client built-in commands remain available when workspace command expansion is From deb4cc2208bf78c6061d48202a590c4e87670945 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:45:33 +0300 Subject: [PATCH 05/48] feat(mecatui): add --permission-mode and show the posture honestly mecatui takes the named token: its posture half configures the embedded server and its session half is the mode this client requests. With no mode flag the client now asks for an unspecified mode, so the server's own default applies, and reads the real mode back. Under connect, a token that sets a posture is refused, since the posture belongs to the remote server. --mode, --posture, and --yolo keep resolving as before, each warning once. The header badge now covers trusted as well as auto and yolo and stays across a session-mode cycle. The help overlay lists all seven tokens with both halves, says cycling never changes the posture, and names whose restart a posture change needs: relaunch mecatui when it hosts the server, or have the server operator restart mecated under connect. Co-Authored-By: Claude Opus 5.5 (1M context) --- cmd/mecatui/client/client.go | 11 + cmd/mecatui/config.go | 45 +++- cmd/mecatui/helpmeta.go | 10 +- cmd/mecatui/main.go | 24 +- cmd/mecatui/permission_mode.go | 160 ++++++++++++ cmd/mecatui/permission_mode_test.go | 226 +++++++++++++++++ cmd/mecatui/ui/builtins.go | 2 +- cmd/mecatui/ui/help.go | 68 +++++ cmd/mecatui/ui/model.go | 9 +- cmd/mecatui/ui/models.go | 2 +- .../ui/permission_mode_adr0365_test.go | 240 ++++++++++++++++++ cmd/mecatui/ui/posture_badge_test.go | 11 +- cmd/mecatui/ui/testdata/help_all_on.golden | 2 +- cmd/mecatui/ui/testdata/help_embedded.golden | 2 +- cmd/mecatui/ui/update.go | 32 ++- cmd/mecatui/ui/view.go | 24 +- 16 files changed, 833 insertions(+), 35 deletions(-) create mode 100644 cmd/mecatui/permission_mode.go create mode 100644 cmd/mecatui/permission_mode_test.go create mode 100644 cmd/mecatui/ui/permission_mode_adr0365_test.go diff --git a/cmd/mecatui/client/client.go b/cmd/mecatui/client/client.go index 44be01357b..6416195ea9 100644 --- a/cmd/mecatui/client/client.go +++ b/cmd/mecatui/client/client.go @@ -719,6 +719,17 @@ func ModeFromString(s string) mecatlv1.PermissionMode { } } +// RequestModeFromString maps the mode a client REQUESTS for a new session. It is +// ModeFromString except that an empty mode means "no preference" and goes out +// UNSPECIFIED, so the server applies its own configured default mode (ADR 0365) +// instead of receiving an explicit DEFAULT. +func RequestModeFromString(s string) mecatlv1.PermissionMode { + if s == "" { + return mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED + } + return ModeFromString(s) +} + // ModeString maps the proto enum to the CLI/UI spelling. Unknown/unspecified values // degrade to "default", matching the server boundary. func ModeString(m mecatlv1.PermissionMode) string { diff --git a/cmd/mecatui/config.go b/cmd/mecatui/config.go index 75b4cf1d70..b9423499c7 100644 --- a/cmd/mecatui/config.go +++ b/cmd/mecatui/config.go @@ -238,6 +238,17 @@ type config struct { // key. Mapped onto app.Config.Posture/PostureFlagSet in embeddedConfig. posture string postureFlagSet bool + // permissionMode is the ADR 0365 named token (--permission-mode). It writes the + // embedded server's posture half (app.Config.PermissionMode) and this client's + // requested session mode. modeFlagSet/yoloFlagSet record the deprecated aliases + // so the combination error and the one-per-alias deprecation WARN key on what + // the operator actually typed. + permissionMode string + permissionModeFlagSet bool + modeFlagSet bool + yoloFlagSet bool + // permissionModeToken is the parsed --permission-mode token (zero when unset). + permissionModeToken app.PermissionModeToken // reasoningEffort is the operator-tier reasoning-effort default for // the EMBEDDED server. reasoningEffortFlagSet records an explicit // --reasoning-effort so CLI out-ranks the operator-global settings.yaml @@ -386,7 +397,8 @@ func parseTransportFlags(mode transportMode, out io.Writer, args []string, brows fs.SetOutput(out) fs.StringVar(&cfg.workspace, "workspace", "", "embedded server only: absolute deployment workspace root (default: cwd); not accepted by connect") registerMicroVMDevelopmentFlags(fs, &cfg.microVMDevRelease, &cfg.microVMDevAcknowledge) - fs.StringVar(&cfg.mode, "mode", "default", "start sessions in permission mode: default, plan, or accept-edits") + fs.StringVar(&cfg.mode, "mode", "default", "deprecated, use --permission-mode: start sessions in permission mode: default, plan, or accept-edits") + fs.StringVar(&cfg.permissionMode, "permission-mode", "", "set the permission mode: "+strings.Join(app.PermissionModeNames(), ", ")+"; the posture half is process-wide for the embedded server, the session half is only the default for new sessions") fs.Func("debug-mcp", "attach configured streaming-HTTP MCP server NAME to debug sessions (repeatable)", func(value string) error { cfg.debugMCP = append(cfg.debugMCP, value) return nil @@ -452,9 +464,9 @@ func parseTransportFlags(mode transportMode, out io.Writer, args []string, brows fs.StringVar(&cfg.anthropicCacheTTL, "anthropic-cache-ttl", "", "set Anthropic prompt-cache lifetime to 5m or 1h (default: 1h on Anthropic, OpenRouter's Anthropic endpoint and the ToolHive gateway); other values are ignored with a warning") fs.BoolVar(&cfg.trustProject, "trust-project", false, "enable project instructions, persona, skills, commands, and allow rules; use only with projects you trust") fs.BoolVar(&cfg.allowAllTools, "yolo", false, - "use yolo posture: allow tools by default and disable delegated-agent command-injection safeguards; explicit deny and ask rules still apply") + "deprecated, use --permission-mode yolo: allow tools by default and disable delegated-agent command-injection safeguards; explicit deny and ask rules still apply") fs.StringVar(&cfg.posture, "posture", "", - "set the permission posture: strict, trusted, auto, or yolo (default: strict); auto and yolo reduce safeguards and are refused as root outside a sandbox") + "deprecated, use --permission-mode: set the permission posture: strict, trusted, auto, or yolo (default: strict); auto and yolo reduce safeguards and are refused as root outside a sandbox") fs.StringVar(&cfg.reasoningEffort, "reasoning-effort", "", "set the default reasoning effort: auto, low, medium, high, xhigh, or max") fs.BoolVar(&cfg.quiet, "quiet", false, @@ -687,6 +699,12 @@ func recordExplicitFlag(f *flag.Flag, cfg *config) { cfg.debugFlagSet = true case "posture": cfg.postureFlagSet = true + case "permission-mode": + cfg.permissionModeFlagSet = true + case "mode": + cfg.modeFlagSet = true + case "yolo": + cfg.yoloFlagSet = true case "shell": cfg.shellFlagSet = true case "subagent-model-router": @@ -734,6 +752,9 @@ func finalizeParsedConfig(fs *flag.FlagSet, cfg *config) error { // settings.yaml keys (mirrors mecated). Extracted to recordExplicitFlag to keep // this function under the cyclomatic-complexity bound. fs.Visit(func(f *flag.Flag) { recordExplicitFlag(f, cfg) }) + if err := parsePermissionModeFlag(cfg); err != nil { + return err + } if cfg.authToken == "" { cfg.authToken = os.Getenv("MECATL_AUTH_TOKEN") @@ -935,6 +956,9 @@ func (c config) validate() error { default: return fmt.Errorf("invalid --mode %q (want default|plan|accept-edits)", c.mode) } + if err := validatePermissionModeFlags(c); err != nil { + return err + } // Provider/posture checks apply ONLY to paths that may embed; the // predicate + its rationale live once on config.mayEmbed. if c.mayEmbed() { @@ -1014,13 +1038,24 @@ func embeddedAuthoritativePosture(c config) app.Posture { Workspace: c.workspace, PermissionsConventional: true, ImportClaudePermissions: true, - Posture: app.ParsePosture(c.posture), - PostureFlagSet: c.postureFlagSet, + Posture: embeddedFlagPosture(c), + PostureFlagSet: c.postureFlagSet || c.permissionModeFlagSet, AllowAllTools: c.allowAllTools, TrustProject: c.trustProject, }) } +// embeddedFlagPosture is the posture the CLI flags request for the pre-TUI checks: +// an explicit --permission-mode token's posture half, else the deprecated --posture. +// Build applies the token through app.Config.PermissionMode itself; this only keeps +// the pre-launch refusal and WARN in step with it. +func embeddedFlagPosture(c config) app.Posture { + if c.permissionModeFlagSet { + return c.permissionModeToken.Posture + } + return app.ParsePosture(c.posture) +} + // embeddedPrivileged is the "root && !sandbox" predicate fed to the posture refusal // (the cmd owns the os/env reads; internal/app takes the bool). It is the SAME value // embeddedConfig threads onto app.Config.Privileged so the fast-path and Build agree. diff --git a/cmd/mecatui/helpmeta.go b/cmd/mecatui/helpmeta.go index 7428c8bfc1..e9542aacd1 100644 --- a/cmd/mecatui/helpmeta.go +++ b/cmd/mecatui/helpmeta.go @@ -118,9 +118,13 @@ var flagApplicabilityByFlag = map[string]flagApplicability{ "context-window-override": {group: groupLLMResilience, common: false, local: true, connect: false}, // ── Permissions (embedded-only) ─────────────────────────────────────── - "posture": {group: groupPermissions, common: true, local: true, connect: false}, - "yolo": {group: groupPermissions, common: true, local: true, connect: false}, - "trust-project": {group: groupPermissions, common: true, local: true, connect: false}, + // --permission-mode applies under connect too: its session half sets this + // client's new sessions, and a non-strict posture half is refused there + // (validatePermissionModeFlags) because the posture is the remote server's. + "permission-mode": {group: groupPermissions, common: true, local: true, connect: true}, + "posture": {group: groupPermissions, common: true, local: true, connect: false}, + "yolo": {group: groupPermissions, common: true, local: true, connect: false}, + "trust-project": {group: groupPermissions, common: true, local: true, connect: false}, // ── Storage (embedded-only) ─────────────────────────────────────────── "store-dir": {group: groupStorage, common: true, local: true, connect: false}, diff --git a/cmd/mecatui/main.go b/cmd/mecatui/main.go index dca377578c..b7cdd46ec6 100644 --- a/cmd/mecatui/main.go +++ b/cmd/mecatui/main.go @@ -253,6 +253,7 @@ func runWithOptions(argv []string, options runOptions) error { // mecatui.log file writer. installBaselineSlog(cfg.quiet) + warnDeprecatedPermissionFlags(os.Stderr, cfg) warnEmbeddedPosture(cfg) reg := buildRegistry(cfg.workspace, cfg.themeDir) @@ -385,12 +386,13 @@ func runWithOptions(argv []string, options runOptions) error { initialSel, wsDefault, wsDefaultSet, globalDefault := launchSelections(store, uiWorkspace, cfg.debugTarget) connectionMode := resolveConnectionMode(cfg) + requestedMode, modeServerDefault := cfg.requestedSessionMode() // Held concretely (not just as the ui interface) because this run OWNS its // shutdown: a /connect restart re-enters runWithOptions and builds a fresh // notifier, so this one must be settled first (see closeAgentLifecycleHook). agentHook := agenthook.New(os.Environ()) deps := applyLaunchIntent(cfg, ui.Deps{ - Session: &sessionAdapter{cl: cl, mode: cfg.mode, debugTarget: cfg.debugTarget, debugMCP: cfg.debugMCP}, + Session: &sessionAdapter{cl: cl, mode: requestedMode, debugTarget: cfg.debugTarget, debugMCP: cfg.debugMCP}, AgentHook: agentLifecycleHook(agentHook), Conv: cl, MCP: cl, @@ -453,11 +455,12 @@ func runWithOptions(argv []string, options runOptions) error { // live/config-first server-side — never recomputed by the client. Embedded mode's // --context-window-override and an external mecated's flag both move the engine // trigger and this echoed denominator. - Model: cfg.model, - Workspace: uiWorkspace, - Mode: cfg.mode, - Resume: resume, - Ctx: ctx, + Model: cfg.model, + Workspace: uiWorkspace, + Mode: requestedMode, + ModeServerDefault: modeServerDefault, + Resume: resume, + Ctx: ctx, // Build identity for the welcome splash (explicit linker stamp, or a // VCS-derived source-build ID when embedded metadata is available). Version: buildinfo.BuildID, @@ -1589,6 +1592,11 @@ func embeddedConfig(cfg config, diag port.Diagnostics) app.Config { // escape it. Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, + // ADR 0365 named token: Build resolves its posture half and puts its + // session half on the server's DefaultMode. An explicit flag out-ranks the + // deprecated --posture and both YAML keys. + PermissionMode: cfg.permissionMode, + PermissionModeFlagSet: cfg.permissionModeFlagSet, // Reasoning-effort tier: operator-tier only; reasoningEffortFlagSet // lets CLI out-rank the operator-global settings.yaml reasoning-effort: key. ReasoningEffort: cfg.reasoningEffort, @@ -1831,13 +1839,13 @@ func (s *sessionAdapter) CreateSession(ctx context.Context, sel client.ModelSele if mode == "" { mode = s.mode } - id, target, caps, resolved, err := s.cl.CreateDebugSession(ctx, s.debugTarget, client.ModeFromString(mode), sel, s.debugMCP...) + id, target, caps, resolved, err := s.cl.CreateDebugSession(ctx, s.debugTarget, client.RequestModeFromString(mode), sel, s.debugMCP...) if target != "" { s.debugTarget = target } return id, caps, resolved, err } - return s.cl.CreateSession(ctx, client.ModeFromString(mode), sel) + return s.cl.CreateSession(ctx, client.RequestModeFromString(mode), sel) } func (s *sessionAdapter) CreateSessionWithExecution(ctx context.Context, sel client.ModelSelection, mode string, choice client.ExecutionChoice) (string, client.Capabilities, client.ResolvedModel, error) { diff --git a/cmd/mecatui/permission_mode.go b/cmd/mecatui/permission_mode.go new file mode 100644 index 0000000000..dcbf0213d5 --- /dev/null +++ b/cmd/mecatui/permission_mode.go @@ -0,0 +1,160 @@ +package main + +import ( + "errors" + "fmt" + "io" + + "github.com/stacklok/mecatl/cmd/mecatui/client" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/app" +) + +// permission_mode.go is mecatui's half of the ADR 0365 --permission-mode flag. +// A token names an exact (posture, session mode) pair. The posture half goes to +// the embedded server's composition (app.Config.PermissionMode); the session half +// is the mode this client requests for the sessions it creates. The deprecated +// --mode, --posture, and --yolo keep resolving exactly as before and each emit one +// pre-launch deprecation WARN. + +// parsePermissionModeFlag parses an explicit --permission-mode into cfg and +// rejects a combination with the deprecated aliases. It runs at parse time so an +// unknown token fails fast on every transport. +func parsePermissionModeFlag(cfg *config) error { + if cfg.permissionModeFlagSet { + tok, err := app.ParsePermissionMode(cfg.permissionMode) + if err != nil { + return fmt.Errorf("--permission-mode: %w", err) + } + cfg.permissionModeToken = tok + } + return validatePermissionModeFlags(*cfg) +} + +// validatePermissionModeFlags enforces the flag-surface rules: --permission-mode +// replaces --mode, --posture, and --yolo rather than combining with them, and +// under `mecatui connect` a token whose posture half is not strict is refused, +// because the posture belongs to the remote server (mirroring --posture, which +// connect rejects outright). --trust-project is not deprecated and still folds. +func validatePermissionModeFlags(c config) error { + if !c.permissionModeFlagSet { + return nil + } + var aliases []string + if c.modeFlagSet { + aliases = append(aliases, "--mode") + } + if c.postureFlagSet { + aliases = append(aliases, "--posture") + } + if c.yoloFlagSet { + aliases = append(aliases, "--yolo") + } + if len(aliases) > 0 { + return fmt.Errorf("--permission-mode cannot be combined with %s; pass one: --permission-mode alone replaces the deprecated flags", joinFlagNames(aliases)) + } + tok := c.permissionModeToken + if c.transportMode == modeConnect && tok.Name != "" && tok.Posture != app.PostureStrict { + return errors.New("--permission-mode " + tok.Name + " sets posture " + tok.Posture.String() + + ", which belongs to the remote server; mecatui connect cannot change it. The server operator must change mecated's configuration and restart it. " + + "To choose the mode of this client's new sessions, pass plan, default, or accept-edits") + } + return nil +} + +func joinFlagNames(names []string) string { + switch len(names) { + case 1: + return names[0] + case 2: + return names[0] + " or " + names[1] + default: + out := "" + for i, n := range names { + switch { + case i == len(names)-1: + out += ", or " + n + case i > 0: + out += ", " + n + default: + out += n + } + } + return out + } +} + +// requestedSessionMode is the session mode this client asks for when it creates a +// session, in the TUI spelling. serverDefault is true when neither +// --permission-mode nor --mode was given: the create then carries no mode, so the +// server's own default applies (embedded: the operator's permissionMode: key; connect: +// the remote server's default). Without that key, and on an older server, the +// server's default is "default", which is exactly what mecatui requested before. +func (c config) requestedSessionMode() (mode string, serverDefault bool) { + switch { + case c.permissionModeFlagSet: + return client.ModeString(client.ModeFromString(string(c.permissionModeToken.SessionMode))), false + case c.modeFlagSet: + return c.mode, false + default: + return "", true + } +} + +// deprecatedPermissionFlagWarnings returns one WARN line per deprecated alias the +// operator typed (--mode, --posture, --yolo), each naming --permission-mode and, +// when one exists, the single token that reproduces the combination. +func deprecatedPermissionFlagWarnings(c config) []string { + if c.permissionModeFlagSet { + // Combined use is a startup error, so no deprecation line is needed. + return nil + } + if !c.modeFlagSet && !c.postureFlagSet && !c.yoloFlagSet { + return nil + } + hint := "no single token names this combination; it still resolves as before" + posture := app.ResolveAliasPosture(app.ParsePosture(c.posture), c.allowAllTools, c.trustProject) + mode := c.mode + if !c.modeFlagSet { + mode = client.ModeDefaultString + } + if tok, ok := app.PermissionModeForPair(posture, sessionModeFromTUI(mode)); ok { + hint = "use --permission-mode " + tok.Name + } + var out []string + add := func(flagName string) { + out = append(out, "mecatui: WARNING: "+flagName+" is deprecated and will be removed; use --permission-mode instead ("+hint+")") + } + if c.modeFlagSet { + add("--mode") + } + if c.postureFlagSet { + add("--posture") + } + if c.yoloFlagSet { + add("--yolo") + } + return out +} + +// warnDeprecatedPermissionFlags prints the deprecation WARNs on the pre-launch +// stderr path (before the alternate screen starts), like warnEmbeddedPosture. +func warnDeprecatedPermissionFlags(w io.Writer, c config) { + for _, line := range deprecatedPermissionFlagWarnings(c) { + _, _ = fmt.Fprintln(w, line) + } +} + +// sessionModeFromTUI maps a TUI mode spelling to the session value app's table +// uses. It goes through the client's spelling grammar first, so every accepted +// --mode spelling maps the same way it does on the wire. +func sessionModeFromTUI(mode string) session.PermissionMode { + switch client.ModeString(client.ModeFromString(mode)) { + case "plan": + return session.ModePlan + case "accept-edits": + return session.ModeAccept + default: + return session.ModeDefault + } +} diff --git a/cmd/mecatui/permission_mode_test.go b/cmd/mecatui/permission_mode_test.go new file mode 100644 index 0000000000..e2a99baf16 --- /dev/null +++ b/cmd/mecatui/permission_mode_test.go @@ -0,0 +1,226 @@ +package main + +import ( + "context" + "strings" + "testing" + "time" + + "github.com/stacklok/mecatl/cmd/mecatui/client" + "github.com/stacklok/mecatl/cmd/mecatui/embed" + "github.com/stacklok/mecatl/cmd/mecatui/ui" + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/internal/app" +) + +// deprecationLines runs the real pre-launch warning path and returns its lines. +func deprecationLines(cfg config) []string { + var b strings.Builder + warnDeprecatedPermissionFlags(&b, cfg) + out := strings.TrimSpace(b.String()) + if out == "" { + return nil + } + return strings.Split(out, "\n") +} + +// TestADR_0365_DeprecatedAliasesStillResolve pins AC6.1 for mecatui: --mode, +// --posture, and --yolo resolve exactly as before and each emits exactly one +// deprecation WARN naming --permission-mode. --trust-project is not deprecated. +func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { + cases := []struct { + name string + args []string + wantPosture app.Posture + wantMode string + wantToken string + }{ + {name: "mode", args: []string{"--mode", "plan"}, wantPosture: app.PostureStrict, wantMode: "plan", wantToken: "plan"}, + {name: "posture", args: []string{"--posture", "auto"}, wantPosture: app.PostureAuto, wantMode: "", wantToken: "auto"}, + {name: "yolo", args: []string{"--yolo"}, wantPosture: app.PostureYolo, wantMode: "", wantToken: "yolo"}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + _, cfg, err := parseTransportFlagsTest(t, modeLocal, append([]string{"--mock", "--workspace", t.TempDir()}, tc.args...)) + if err != nil { + t.Fatalf("parse %v: %v", tc.args, err) + } + if got := embeddedAuthoritativePosture(cfg); got != tc.wantPosture { + t.Errorf("posture = %v, want %v", got, tc.wantPosture) + } + if mode, _ := cfg.requestedSessionMode(); mode != tc.wantMode { + t.Errorf("requested session mode = %q, want %q", mode, tc.wantMode) + } + ac := embeddedConfig(cfg, nil) + if ac.PermissionModeFlagSet { + t.Error("a deprecated alias must not set PermissionModeFlagSet") + } + lines := deprecationLines(cfg) + if len(lines) != 1 { + t.Fatalf("deprecation WARNs = %d (%q), want exactly 1", len(lines), lines) + } + for _, want := range []string{"WARNING", tc.args[0], "--permission-mode " + tc.wantToken} { + if !strings.Contains(lines[0], want) { + t.Errorf("WARN %q missing %q", lines[0], want) + } + } + }) + } + t.Run("each alias warns once", func(t *testing.T) { + _, cfg, err := parseTransportFlagsTest(t, modeLocal, []string{"--mock", "--workspace", t.TempDir(), "--mode", "plan", "--posture", "auto", "--yolo"}) + if err != nil { + t.Fatalf("parse: %v", err) + } + lines := deprecationLines(cfg) + if len(lines) != 3 { + t.Fatalf("deprecation WARNs = %q, want one per alias", lines) + } + for i, flagName := range []string{"--mode", "--posture", "--yolo"} { + if !strings.Contains(lines[i], flagName+" is deprecated") || !strings.Contains(lines[i], "--permission-mode") { + t.Errorf("WARN %d = %q, want %s deprecation naming --permission-mode", i, lines[i], flagName) + } + } + }) + t.Run("trust-project and the new flag do not warn", func(t *testing.T) { + for _, args := range [][]string{{"--trust-project"}, {"--permission-mode", "auto"}, nil} { + _, cfg, err := parseTransportFlagsTest(t, modeLocal, append([]string{"--mock", "--workspace", t.TempDir()}, args...)) + if err != nil { + t.Fatalf("parse %v: %v", args, err) + } + if lines := deprecationLines(cfg); len(lines) != 0 { + t.Errorf("%v emitted deprecation WARNs %q", args, lines) + } + } + }) +} + +// TestADR_0365_PermissionModeConflictsWithAliases pins that --permission-mode +// combined with any deprecated alias is a startup error telling the operator to +// pass one, and that an unknown token fails fast naming the valid set. +func TestADR_0365_PermissionModeConflictsWithAliases(t *testing.T) { + for _, alias := range [][]string{{"--mode", "plan"}, {"--posture", "auto"}, {"--yolo"}} { + args := append([]string{"--mock", "--workspace", "/abs", "--permission-mode", "plan"}, alias...) + _, _, err := parseTransportFlagsTest(t, modeLocal, args) + if err == nil { + t.Fatalf("%v: want a startup error", args) + } + if !strings.Contains(err.Error(), "--permission-mode cannot be combined with "+alias[0]) || !strings.Contains(err.Error(), "pass one") { + t.Errorf("%v: error %q must name the conflict and say to pass one", args, err) + } + } + _, _, err := parseTransportFlagsTest(t, modeLocal, []string{"--mock", "--workspace", "/abs", "--permission-mode", "accept-all"}) + if err == nil || !strings.Contains(err.Error(), "trusted-accept-edits") { + t.Fatalf("unknown token error = %v, want the valid token list", err) + } + if _, _, err := parseTransportFlagsTest(t, modeLocal, []string{"--mock", "--workspace", "/abs", "--permission-mode", "plan", "--trust-project"}); err != nil { + t.Errorf("--trust-project is not deprecated and must combine: %v", err) + } +} + +// TestADR_0365_ConnectRefusesPostureHalf pins the connect behaviour: the session +// half of a token applies to this client's sessions, while a non-strict posture +// half is refused because the posture belongs to the remote server. +func TestADR_0365_ConnectRefusesPostureHalf(t *testing.T) { + _, cfg, err := parseTransportFlagsTest(t, modeConnect, []string{"--permission-mode", "accept-edits"}) + if err != nil { + t.Fatalf("session-only token under connect: %v", err) + } + if mode, serverDefault := cfg.requestedSessionMode(); mode != "accept-edits" || serverDefault { + t.Errorf("connect session half = %q (server default %v), want accept-edits", mode, serverDefault) + } + for _, tok := range []string{"trusted", "trusted-accept-edits", "auto", "yolo"} { + _, _, err := parseTransportFlagsTest(t, modeConnect, []string{"--permission-mode", tok}) + if err == nil { + t.Fatalf("connect --permission-mode %s: want an error", tok) + } + if !strings.Contains(err.Error(), "belongs to the remote server") || !strings.Contains(err.Error(), "mecated") { + t.Errorf("connect --permission-mode %s error %q must name the server's ownership", tok, err) + } + } +} + +// TestADR_0365_VocabularyMatchesComposition keeps the TUI's display copy of the +// token table identical to the composition layer's contract. +func TestADR_0365_VocabularyMatchesComposition(t *testing.T) { + vocab := ui.PermissionModeVocabulary() + names := app.PermissionModeNames() + if len(vocab) != len(names) { + t.Fatalf("TUI lists %d tokens, composition has %d", len(vocab), len(names)) + } + for i, name := range names { + tok, err := app.ParsePermissionMode(name) + if err != nil { + t.Fatal(err) + } + want := ui.PermissionModeEntry{ + Name: tok.Name, + Posture: tok.Posture.String(), + SessionMode: client.ModeString(client.ModeFromString(string(tok.SessionMode))), + } + if vocab[i] != want { + t.Errorf("row %d = %+v, want %+v", i, vocab[i], want) + } + } +} + +// TestADR_0365_DefaultsReproduceCurrentBehaviour pins AC6.3 for mecatui end to +// end: the parsed flags build the real embedded server, the real client creates a +// session through the real sessionAdapter, and the server-reported posture and +// session mode match what mecatui produced before ADR 0365. +func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { + cases := []struct { + name string + args []string + wantPosture string + wantMode string + }{ + {name: "unconfigured", args: nil, wantPosture: "strict", wantMode: "default"}, + {name: "mode plan", args: []string{"--mode", "plan"}, wantPosture: "strict", wantMode: "plan"}, + {name: "permission-mode plan", args: []string{"--permission-mode", "plan"}, wantPosture: "strict", wantMode: "plan"}, + {name: "permission-mode trusted-accept-edits", args: []string{"--permission-mode", "trusted-accept-edits"}, wantPosture: "trusted", wantMode: "accept-edits"}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) + defer cancel() + workspace := t.TempDir() + _, cfg, err := parseTransportFlagsTest(t, modeLocal, append([]string{"--mock", "--workspace", workspace}, tc.args...)) + if err != nil { + t.Fatalf("parse: %v", err) + } + ac := embeddedConfig(cfg, nil) + ac.MockProvider = mockllm.New() + ac.StoreDir = "" + ac.MemoryDir = t.TempDir() + ac.UserModelDir = t.TempDir() + ac.ToolHiveEnabled = false + srv, err := embed.Start(ctx, ac, embed.PerfConfig{}) + if err != nil { + t.Fatalf("start embedded server: %v", err) + } + defer func() { _ = srv.Close() }() + cl, err := client.Dial(client.DialConfig{Server: srv.Target()}) + if err != nil { + t.Fatalf("dial: %v", err) + } + defer func() { _ = cl.Close() }() + + requested, _ := cfg.requestedSessionMode() + adapter := &sessionAdapter{cl: cl, mode: requested} + id, caps, _, err := adapter.CreateSession(ctx, client.ModelSelection{}, requested) + if err != nil { + t.Fatalf("create session: %v", err) + } + snap, err := adapter.GetSession(ctx, id) + if err != nil { + t.Fatalf("get session: %v", err) + } + if caps.Posture != tc.wantPosture { + t.Errorf("posture = %q, want %q", caps.Posture, tc.wantPosture) + } + if snap.Mode != tc.wantMode { + t.Errorf("session mode = %q, want %q", snap.Mode, tc.wantMode) + } + }) + } +} diff --git a/cmd/mecatui/ui/builtins.go b/cmd/mecatui/ui/builtins.go index 9ce0dd0db6..a84c363d7f 100644 --- a/cmd/mecatui/ui/builtins.go +++ b/cmd/mecatui/ui/builtins.go @@ -468,7 +468,7 @@ func (m Model) runHelp() (tea.Model, tea.Cmd) { return m, nil } deps := (&m).surfaceDeps() - m.modal = &helpState{deps: deps, lines: strings.Split(helpBody(deps.theme, deps.caps, deps.marks), "\n")} + m.modal = &helpState{deps: deps, lines: strings.Split(m.helpBody(), "\n")} m.prompt.Blur() return m, nil } diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 6a367faf2c..5afe10e8a4 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -154,6 +154,20 @@ func helpScrollIndicator(hk helpKeys, start, end, total int) string { // hk carries the LIVE key markings from the model's keyMap, so a rebinding // propagates here. func helpBody(th theme.Theme, caps client.Capabilities, hk helpKeys) string { + return helpBodyFor(th, caps, hk, true) +} + +// helpBody renders the overlay body for this model's transport: the permission +// mode section's restart guidance differs between the embedded server and +// `mecatui connect` (ADR 0365). +func (m Model) helpBody() string { + return helpBodyFor(m.deps.Theme, m.caps, m.helpKeyMarkings(), m.deps.Embedded) +} + +// helpBodyFor is helpBody with an explicit transport. embedded selects whose +// restart a posture change needs: the operator's own mecatui relaunch, or the +// remote server operator's mecated restart. +func helpBodyFor(th theme.Theme, caps client.Capabilities, hk helpKeys, embedded bool) string { heading := th.Style("toolName") body := th.Style("toolArgs") var b strings.Builder @@ -223,6 +237,8 @@ func helpBody(th theme.Theme, caps client.Capabilities, hk helpKeys) string { ) writeHelpRows(&b, th, inspectRows) + writeHelpPermissionModes(&b, th, hk, embedded) + b.WriteString("\n" + heading.Render("Conversation and navigation") + "\n") writeHelpRows(&b, th, []helpRow{ {key: hk.selectAll, action: "select all prompt text"}, @@ -294,6 +310,58 @@ func helpBody(th theme.Theme, caps client.Capabilities, hk helpKeys) string { return b.String() } +// PermissionModeEntry is one row of the ADR 0365 permission-mode vocabulary as +// the TUI displays it: the token, the process-wide posture it sets, and the +// session mode new sessions start in (the TUI spelling). +type PermissionModeEntry struct { + Name string + Posture string + SessionMode string +} + +// PermissionModeVocabulary is the token table the help overlay lists. The ui +// cannot import the composition layer, so this is a display copy; a test in the +// mecatui main package pins it to app.ParsePermissionMode so the two never drift. +func PermissionModeVocabulary() []PermissionModeEntry { + return []PermissionModeEntry{ + {Name: "plan", Posture: postureStrict, SessionMode: "plan"}, + {Name: "default", Posture: postureStrict, SessionMode: client.ModeDefaultString}, + {Name: "accept-edits", Posture: postureStrict, SessionMode: "accept-edits"}, + {Name: "trusted", Posture: postureTrusted, SessionMode: client.ModeDefaultString}, + {Name: "trusted-accept-edits", Posture: postureTrusted, SessionMode: "accept-edits"}, + {Name: "auto", Posture: postureAuto, SessionMode: client.ModeDefaultString}, + {Name: "yolo", Posture: postureYolo, SessionMode: client.ModeDefaultString}, + } +} + +// writeHelpPermissionModes lists every permission-mode token with its two +// halves, states that the posture half is process-wide while the session half is +// only a new-session default, that cycling the session mode never changes the +// posture, and whose restart a posture change needs (ADR 0365, AC5.2/AC5.5). +// Runtime selection of a posture from the TUI is deliberately not offered. +func writeHelpPermissionModes(b *strings.Builder, th theme.Theme, hk helpKeys, embedded bool) { + b.WriteString("\n" + th.Style("toolName").Render("Permission modes (--permission-mode, set at launch)") + "\n") + vocab := PermissionModeVocabulary() + rows := make([]helpRow, 0, len(vocab)) + for _, e := range vocab { + rows = append(rows, helpRow{key: e.Name, action: "posture " + e.Posture + " (process-wide) · new sessions start in " + e.SessionMode}) + } + writeHelpRows(b, th, rows) + writeHelpBodyLines(b, th, + "The posture half applies to the whole server and is fixed when it starts.", + "The session half is only the default for new sessions.", + "Cycling the session mode ("+hk.modeSwitch+") never changes the posture half.", + ) + if embedded { + writeHelpBodyLines(b, th, + "To change the posture, quit and relaunch: mecatui --permission-mode ") + return + } + writeHelpBodyLines(b, th, + "This client is connected to a remote server, which owns the posture.", + "To change it, the server operator must change mecated's configuration and restart it.") +} + // writeHelpBodyLines renders each line independently so helpRenderedLines can // safely window the ANSI output without severing a style sequence. func writeHelpBodyLines(b *strings.Builder, th theme.Theme, lines ...string) { diff --git a/cmd/mecatui/ui/model.go b/cmd/mecatui/ui/model.go index cd94222afa..33fee06436 100644 --- a/cmd/mecatui/ui/model.go +++ b/cmd/mecatui/ui/model.go @@ -294,6 +294,13 @@ type Deps struct { Workspace string Mode string Model string + // ModeServerDefault asks the server to choose the first session's permission + // mode (ADR 0365): no --permission-mode or --mode was given, so the create + // carries an unspecified mode and the server's configured default applies + // (embedded: the operator's permissionMode: key; connect: the remote server's + // own default). The created session's mode is read back with GetSession, so the + // header never guesses it. Mode is then only the pre-session display fallback. + ModeServerDefault bool // Resume is a statically validated existing chat selected before Bubble Tea // starts. Its authoritative transcript is adopted without CreateSession; nil // preserves the new-session default. @@ -1114,7 +1121,7 @@ func New(deps Deps) Model { // rejects the create, createSessionCmd's fallback leg retries on the default and // surfaces a loud warning (connectFallbackMsg) — connect still completes. createModelSelection: deps.InitialModel, - activeMode: client.ModeString(client.ModeFromString(deps.Mode)), + activeMode: initialActiveMode(deps), modelCatalog: modelCatalog{active: deps.InitialModel, globalDefault: deps.GlobalDefault}, // Seed the CLI-supplied seed prompt (-p/--prompt + --prompt-file) for // one-shot auto-submit on the FIRST session ready. diff --git a/cmd/mecatui/ui/models.go b/cmd/mecatui/ui/models.go index 6fd2b675e5..9736e126b9 100644 --- a/cmd/mecatui/ui/models.go +++ b/cmd/mecatui/ui/models.go @@ -125,7 +125,7 @@ func (m Model) restartOnModelCmd(oldID string, sel client.ModelSelection) tea.Cm if err != nil { return restartFailedMsg{err: err, model: modelSelLabel(sel)} } - return client.SessionReadyMsg{SessionID: id, Capabilities: caps, ResolvedModel: resolved, Mode: m.desiredMode()} + return client.SessionReadyMsg{SessionID: id, Capabilities: caps, ResolvedModel: resolved, Mode: createdSessionMode(deps, id, m.desiredMode())} } } diff --git a/cmd/mecatui/ui/permission_mode_adr0365_test.go b/cmd/mecatui/ui/permission_mode_adr0365_test.go new file mode 100644 index 0000000000..315bd099e3 --- /dev/null +++ b/cmd/mecatui/ui/permission_mode_adr0365_test.go @@ -0,0 +1,240 @@ +package ui + +import ( + "context" + "strings" + "testing" + "time" + + tea "charm.land/bubbletea/v2" + + "github.com/stacklok/mecatl/cmd/mecatui/client" + "github.com/stacklok/mecatl/cmd/mecatui/theme" +) + +// adr0365Model is a live model bound to a session whose server reports posture. +func adr0365Model(t *testing.T, conv *fakeConv, posture string, embedded bool) Model { + t.Helper() + m := newTestModelFromDeps(Deps{ + Session: conv, + Conv: conv, + Theme: theme.New("aztec", theme.AztecPalette()), + Mode: "default", + Embedded: embedded, + Ctx: context.Background(), + }) + return applyAll(m, + tea.WindowSizeMsg{Width: 140, Height: 30}, + client.SessionReadyMsg{SessionID: "sess-test-0001", Mode: "default", Capabilities: client.Capabilities{Posture: posture}}, + ) +} + +// statusMode is the session mode the header's status surface renders as "mode X". +func statusMode(m Model) string { + return m.statusLineInput(time.Now()).Session.Mode +} + +// cycleMode presses the real ModeSwitch chord and feeds the resulting SetMode +// command back through Update, as the Bubble Tea runtime would. +func cycleMode(t *testing.T, m Model) Model { + t.Helper() + mm, cmd := m.Update(modeKey()) + m = mm.(Model) + if cmd == nil { + t.Fatal("mode switch chord issued no SetMode command") + } + return applyAll(m, cmd()) +} + +// TestADR_0365_ModeSwitchCycleUnchanged pins AC5.1: the session mode cycle offers +// exactly the three session modes in the same order as before ADR 0365. No +// posture-bearing token becomes reachable from the keybinding. +func TestADR_0365_ModeSwitchCycleUnchanged(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := adr0365Model(t, conv, postureStrict, true) + want := []string{"plan", "accept-edits", "default", "plan"} + for range want { + m = cycleMode(t, m) + } + got := conv.setModes() + if strings.Join(got, ",") != strings.Join(want, ",") { + t.Fatalf("SetMode cycle = %v, want %v", got, want) + } + if m.activeMode != "plan" { + t.Fatalf("active mode after cycle = %q, want plan", m.activeMode) + } +} + +// TestADR_0365_HelpOverlayShowsVocabularyAndScopeSplit pins AC5.2: every token is +// listed with its posture half marked process-wide and its session half marked as +// the new-session default, with the exact invocation and the statement that +// cycling the session mode never changes the posture half. +func TestADR_0365_HelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := adr0365Model(t, conv, postureStrict, true) + body := stripANSIstr(m.helpBody()) + + // The ADR 0365 table, written out independently of PermissionModeVocabulary. + want := []struct{ token, posture, session string }{ + {"plan", "strict", "plan"}, + {"default", "strict", "default"}, + {"accept-edits", "strict", "accept-edits"}, + {"trusted", "trusted", "default"}, + {"trusted-accept-edits", "trusted", "accept-edits"}, + {"auto", "auto", "default"}, + {"yolo", "yolo", "default"}, + } + for _, w := range want { + row := "posture " + w.posture + " (process-wide) · new sessions start in " + w.session + found := false + for _, line := range strings.Split(body, "\n") { + fields := strings.Fields(strings.Trim(line, "┃ ")) + if len(fields) > 0 && fields[0] == w.token && strings.Contains(line, row) { + found = true + break + } + } + if !found { + t.Errorf("help overlay has no row for token %q with %q", w.token, row) + } + } + for _, phrase := range []string{ + "--permission-mode", + "The posture half applies to the whole server and is fixed when it starts.", + "The session half is only the default for new sessions.", + "Cycling the session mode (" + m.helpKeyMarkings().modeSwitch + ") never changes the posture half.", + "mecatui --permission-mode ", + } { + if !strings.Contains(body, phrase) { + t.Errorf("help overlay missing %q", phrase) + } + } +} + +// TestADR_0365_HeaderShowsPostureWhenAboveStrict pins AC5.3: the header shows the +// session mode, and a posture badge for every tier above strict (trusted now +// included), sourced from the server-reported caps.Posture. +func TestADR_0365_HeaderShowsPostureWhenAboveStrict(t *testing.T) { + cases := []struct { + posture string + badge string // "" = no badge + }{ + {postureStrict, ""}, + {postureTrusted, trustedBadgeText}, + {postureAuto, "⚠ auto"}, + {postureYolo, "YOLO"}, + } + for _, tc := range cases { + t.Run(tc.posture, func(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := adr0365Model(t, conv, tc.posture, true) + header := stripANSIstr(m.renderHeader()) + if got := statusMode(m); got != "default" { + t.Errorf("status mode = %q, want default", got) + } + badge, _ := m.postureBadgeRender() + if tc.badge == "" { + if badge != "" || strings.Contains(header, "posture") || strings.Contains(header, "strict") { + t.Errorf("strict must render no posture badge, got %q", header) + } + return + } + if badge == "" || !strings.Contains(header, tc.badge) { + t.Errorf("posture %s: header missing badge %q: %q", tc.posture, tc.badge, header) + } + }) + } +} + +// TestADR_0365_HeaderKeepsPostureAcrossModeCycle pins AC5.4: under auto, cycling +// the session mode through plan and back to default keeps the auto badge on every +// frame, including the pending frame before the server confirms each switch. +func TestADR_0365_HeaderKeepsPostureAcrossModeCycle(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := adr0365Model(t, conv, postureAuto, true) + assertAuto := func(step, wantMode string) { + t.Helper() + header := stripANSIstr(m.renderHeader()) + if !strings.Contains(header, autoBadgeText) { + t.Fatalf("%s: header lost the auto posture: %q", step, header) + } + if got := statusMode(m); got != wantMode { + t.Fatalf("%s: status mode = %q, want %s", step, got, wantMode) + } + } + assertAuto("start", "default") + for _, next := range []string{"plan", "accept-edits", "default"} { + mm, cmd := m.Update(modeKey()) + m = mm.(Model) + if cmd == nil { + t.Fatalf("switch to %s issued no command", next) + } + assertAuto("pending "+next, next+" pending") + m = applyAll(m, cmd()) + assertAuto("confirmed "+next, next) + } +} + +// TestADR_0365_HelpOverlayNamesWhoseRestart pins AC5.5: the embedded server's +// help gives the mecatui relaunch invocation; under `mecatui connect` it names +// the server operator's mecated restart and offers no local invocation. +func TestADR_0365_HelpOverlayNamesWhoseRestart(t *testing.T) { + render := func(embedded bool) string { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := adr0365Model(t, conv, postureAuto, embedded) + return stripANSIstr(m.helpBody()) + } + embedded := render(true) + if !strings.Contains(embedded, "quit and relaunch: mecatui --permission-mode ") { + t.Errorf("embedded help missing the mecatui relaunch invocation:\n%s", embedded) + } + if strings.Contains(embedded, "server operator") { + t.Errorf("embedded help must not defer to a server operator:\n%s", embedded) + } + connect := render(false) + if !strings.Contains(connect, "the server operator must change mecated's configuration and restart it") { + t.Errorf("connect help missing the server-operator guidance:\n%s", connect) + } + if strings.Contains(connect, "mecatui --permission-mode") || strings.Contains(connect, "relaunch") { + t.Errorf("connect help must offer no local invocation:\n%s", connect) + } +} + +// TestModeServerDefaultRequestsUnspecifiedAndReadsBack pins the ADR 0365 session +// half under ModeServerDefault: the first create requests no mode, so the server's +// default applies, and the header shows the mode the server reports rather than +// guessing "default". +func TestModeServerDefaultRequestsUnspecifiedAndReadsBack(t *testing.T) { + // The fake keeps its current mode when a create requests none, so "plan" here + // stands for a server whose configured default is plan. + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "plan"} + m := newTestModelFromDeps(Deps{ + Session: conv, + Conv: conv, + Theme: theme.New("aztec", theme.AztecPalette()), + ModeServerDefault: true, + Ctx: context.Background(), + }) + if got := m.desiredMode(); got != "" { + t.Fatalf("desiredMode before any session = %q, want empty (server default)", got) + } + msg := m.createSessionCmd()() + ready, ok := msg.(client.SessionReadyMsg) + if !ok { + t.Fatalf("create returned %T, want SessionReadyMsg", msg) + } + if ready.Mode != "plan" { + t.Fatalf("ready mode = %q, want the server-reported plan", ready.Mode) + } + if conv.mode != "plan" { + t.Fatalf("create overrode the server default with %q", conv.mode) + } + m = applyAll(m, tea.WindowSizeMsg{Width: 120, Height: 30}, ready) + if got := statusMode(m); got != "plan" { + t.Fatalf("status mode = %q, want plan", got) + } + // Once known, later creates carry the current mode explicitly, as before. + if got := m.desiredMode(); got != "plan" { + t.Fatalf("desiredMode after ready = %q, want plan", got) + } +} diff --git a/cmd/mecatui/ui/posture_badge_test.go b/cmd/mecatui/ui/posture_badge_test.go index 9e3d086925..c7f533dd30 100644 --- a/cmd/mecatui/ui/posture_badge_test.go +++ b/cmd/mecatui/ui/posture_badge_test.go @@ -12,8 +12,9 @@ import ( ) // TestPostureBadgeShownForAutoYolo asserts the header renders the auto/yolo chrome -// badge when the server reports an allow-all posture, and NO badge for strict/trusted -// (and an empty/older-server posture) — the goldens-stability guarantee. Under +// badge when the server reports an allow-all posture, the quieter trusted badge for +// trusted (ADR 0365), and NO badge for strict (and an empty/older-server posture) — +// the goldens-stability guarantee. Under // MECATUI_NO_EMOJI the yolo badge is the clean " YOLO " pill with NO lightning bolt and // NO VS16; auto is "⚠ auto". The badge is sourced from caps.Posture (SessionReadyMsg), // NOT the per-session mode segment. @@ -24,7 +25,7 @@ func TestPostureBadgeShownForAutoYolo(t *testing.T) { }{ {"", ""}, {"strict", ""}, - {"trusted", ""}, + {"trusted", "trusted"}, {"auto", "⚠ auto"}, {"yolo", "YOLO"}, } @@ -36,8 +37,8 @@ func TestPostureBadgeShownForAutoYolo(t *testing.T) { raw := m.renderHeader() header := stripANSIstr(raw) if tc.wantBadge == "" { - // No badge for strict/trusted/unset: no posture glyph or word may appear. - if strings.Contains(header, "⚠") || strings.Contains(header, "⚡") || strings.Contains(header, "YOLO") { + // No badge for strict/unset: no posture glyph or word may appear. + if strings.Contains(header, "⚠") || strings.Contains(header, "⚡") || strings.Contains(header, "YOLO") || strings.Contains(header, "posture") { t.Errorf("posture %q: header must show NO badge, got %q", tc.posture, header) } continue diff --git a/cmd/mecatui/ui/testdata/help_all_on.golden b/cmd/mecatui/ui/testdata/help_all_on.golden index bf2230d6a1..7f676681ae 100644 --- a/cmd/mecatui/ui/testdata/help_all_on.golden +++ b/cmd/mecatui/ui/testdata/help_all_on.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 75 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 89 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/testdata/help_embedded.golden b/cmd/mecatui/ui/testdata/help_embedded.golden index 2e243bf2c4..1a237359e3 100644 --- a/cmd/mecatui/ui/testdata/help_embedded.golden +++ b/cmd/mecatui/ui/testdata/help_embedded.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 74 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 88 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/update.go b/cmd/mecatui/ui/update.go index be1819c0ab..91dc3426b6 100644 --- a/cmd/mecatui/ui/update.go +++ b/cmd/mecatui/ui/update.go @@ -2637,9 +2637,37 @@ func (m Model) desiredMode() string { if m.activeMode != "" { return m.activeMode } + if m.deps.ModeServerDefault { + // No session mode known yet and none requested: let the server's default apply. + return "" + } return client.ModeString(client.ModeFromString(m.deps.Mode)) } +// initialActiveMode seeds the model's active mode. Under ModeServerDefault it is +// unknown until the server reports the created session's mode. +func initialActiveMode(deps Deps) string { + if deps.ModeServerDefault { + return "" + } + return client.ModeString(client.ModeFromString(deps.Mode)) +} + +// createdSessionMode is the mode a freshly created session is in. An explicit +// request is what the server applied; an unspecified request (ModeServerDefault) +// is read back from the server, because CreateSessionResponse carries no mode. A +// failed read-back reports "" so the header keeps its fallback rather than guess. +func createdSessionMode(deps Deps, id, requested string) string { + if requested != "" || deps.Session == nil { + return requested + } + snap, err := deps.Session.GetSession(deps.Ctx, id) + if err != nil { + return "" + } + return snap.Mode +} + func (m Model) switchMode(mode string) (tea.Model, tea.Cmd) { mode = client.ModeString(client.ModeFromString(mode)) if m.sessionID == "" { @@ -5066,7 +5094,7 @@ func (m Model) createSessionCmd() tea.Cmd { return func() tea.Msg { id, caps, resolved, err := deps.Session.CreateSession(deps.Ctx, sel, m.desiredMode()) if err == nil { - return client.SessionReadyMsg{SessionID: id, Capabilities: caps, ResolvedModel: resolved, Mode: m.desiredMode()} + return client.SessionReadyMsg{SessionID: id, Capabilities: caps, ResolvedModel: resolved, Mode: createdSessionMode(deps, id, m.desiredMode())} } if sel.IsZero() || !client.IsInvalidArgument(err) { reason, _ := client.AuthFailure(err, deps.BearerBacked) @@ -5083,7 +5111,7 @@ func (m Model) createSessionCmd() tea.Cmd { return client.ConnectErrMsg{Err: err} } return connectFallbackMsg{ - ready: client.SessionReadyMsg{SessionID: id, Capabilities: caps, ResolvedModel: resolved, Mode: m.desiredMode()}, + ready: client.SessionReadyMsg{SessionID: id, Capabilities: caps, ResolvedModel: resolved, Mode: createdSessionMode(deps, id, m.desiredMode())}, rejected: sel, err: err, } diff --git a/cmd/mecatui/ui/view.go b/cmd/mecatui/ui/view.go index 0e7f510c6e..69f17bec14 100644 --- a/cmd/mecatui/ui/view.go +++ b/cmd/mecatui/ui/view.go @@ -185,6 +185,10 @@ const ( // autoBadgeText is the auto-posture badge: amber inline WARNING text (no pill). const autoBadgeText = "⚠ auto" +// trustedBadgeText is the trusted-posture badge: inline warning-styled text naming +// the posture, with no glyph so it reads quieter than the allow-all tiers. +const trustedBadgeText = "trusted" + // yoloPillText is the YOLO pill's CONTENT — just the word, padded by a space each side // so the filled dangerPill chip has visual breathing room around "YOLO". The pill never // contains the lightning bolt: the emoji (when shown) rides OUTSIDE the pill as plain @@ -202,12 +206,13 @@ const yoloBoltPrefix = "⚡️ " // postureBadgeRender builds the right-aligned operator-posture chrome badge — the STYLED // string ready to drop into the header AND its visible (plain) cell width for the -// fit/shed math. It surfaces the SERVER-WIDE automation posture (m.caps.Posture) for the -// allow-all tiers ONLY — strict/trusted/unknown render NO badge, so the -// steady-state frame and the goldens stay byte-identical. It is DISTINCT from the -// per-session `mode` segment. +// fit/shed math. It surfaces the SERVER-WIDE posture (m.caps.Posture) whenever it is +// above strict — strict/unknown render NO badge, so the steady-state frame and the +// goldens stay byte-identical. It is DISTINCT from the per-session `mode` segment, and a +// session-mode cycle never changes it (ADR 0365). // // Tiers: +// - trusted → warning-styled inline text "trusted". // - auto → amber inline WARNING text "⚠ auto". // - yolo → a clean filled DANGER PILL (dangerPill style) of " YOLO ", optionally // PRECEDED by a PLAIN ⚡️ emoji bolt when m.emojiOK (seeded once at New). The bolt is @@ -230,9 +235,14 @@ func (m Model) postureBadgeRender() (styled string, plainWidth int) { return yoloBoltPrefix + pill, lipgloss.Width(yoloBoltPrefix) + w } return pill, w - case postureStrict, postureTrusted: - // The non-allow-all tiers carry no badge — the steady-state frame stays - // byte-identical (the goldens are captured at strict). + case postureTrusted: + // Above strict (ADR 0365, AC5.3): the project's rules and instructions are + // honoured process-wide, so the header must not read as a plain default + // session. Warning-styled text, no glyph, quieter than auto's. + return m.deps.Theme.Style("warning").Render(trustedBadgeText), lipgloss.Width(trustedBadgeText) + case postureStrict: + // Strict carries no badge — the steady-state frame stays byte-identical (the + // goldens are captured at strict). return "", 0 default: // Unknown / older-server posture: no badge. From ed2caf7abb97acc68b525d7626875858ddb073a1 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:45:33 +0300 Subject: [PATCH 06/48] docs(permissions): document the permission-mode vocabulary Rewrite the permissions and posture guide around --permission-mode: the seven tokens and what each sets, the two lifetimes, whose restart a posture change needs, both startup refusals, the three checker states, the headless reviewer default and its opt-out, and the subagent asymmetry. It states plainly that autonomy is chosen at launch, not from inside the TUI. Deployment pages for mecated, mecatequi, and mecak8s drop --posture for the new flag and describe the declared checker choice. Co-Authored-By: Claude Opus 5.5 (1M context) --- user-docs/building/ci/mecatequi.md | 37 ++- .../permissions-and-posture.md | 235 +++++++++++++----- user-docs/mecatui/using-the-tui.md | 7 +- user-docs/operating/mecak8s.md | 26 +- user-docs/operating/mecated.md | 10 +- .../operating/mecated/secure-and-expose.md | 48 ++-- 6 files changed, 265 insertions(+), 98 deletions(-) diff --git a/user-docs/building/ci/mecatequi.md b/user-docs/building/ci/mecatequi.md index 0ef0717bca..c59828b3c1 100644 --- a/user-docs/building/ci/mecatequi.md +++ b/user-docs/building/ci/mecatequi.md @@ -246,7 +246,7 @@ corrupt both. |`--workspace`|cwd|Session workspace root. Must be a git repository top level.| |`--default-provider`|`""`|Provider ID: `openai`, `openai-codex`, `openrouter`, `anthropic`, or `opencode`.| |`--model`|`""`|Per-session passthrough model ID. Accepts any ID the provider serves, including IDs newer than the embedded catalog. Prefer this over `--default-model` for newer models.| -|`--posture`|`""` (strict)|Permission posture. Use `auto` for autonomous CI. With `strict` and `--headless`, a main-agent permission ask cancels the run and exits 1.| +|`--permission-mode`|`default`|Permission mode. Use `auto` for autonomous CI, together with `--guardrails-model` or `--guardrails off`. With `default` and `--headless`, a main-agent permission ask cancels the run and exits 1. `--posture` is a deprecated alias.| |`--trust-project`|`false`|Trust this workspace for project content and read-only child shell access. No posture grants project trust in headless mode. Without this flag or a declared or remembered trust decision, Mecatl ignores project content such as `AGENTS.md` and does not give read-only children a shell.| |`--headless`|`true`|Controls child permission requests. The default denies them or routes them to the optional ask reviewer. See [Headless posture and permission asks](#headless-posture-and-permission-asks).| |`--timeout`|`0` (disabled)|Wall-clock bound on the whole run (for example, `40m`). A timeout-cancelled run exits 1 with `stop_reason: cancelled`.| @@ -300,22 +300,35 @@ Metrics use bounded role labels and do not include session or model IDs. `mecatequi` defaults to `--headless=true`. Permission asks behave differently for the main agent and its children. -Child asks from subagents, team members, and parallel branches are denied by -default. `--subagent-ask-reviewer` enables a tool-less, one-turn LLM reviewer -that can approve the current call only. A reviewer error leaves the call denied. -This flag applies only in headless mode. +Child asks from subagents, team members, and parallel branches go to a +tool-less, one-turn LLM reviewer under `auto` and `yolo`, which can approve the +current call only. The reviewer uses the `ask-reviewer` model slot, or the +session model. Set `--subagent-ask-reviewer ` to choose its model, or +`--subagent-ask-reviewer off` to deny child asks instead. In other modes child +asks are denied unless you set a reviewer model. A reviewer error leaves the +call denied. The reviewer applies only in headless mode. `--headless=false` surfaces child asks instead. `mecatequi` has no approval interface, so the first surfaced ask cancels the run, produces `stop_reason: cancelled`, and exits 1. -With `--posture strict` and `--headless`, the main agent has no approver. Its -first permission ask cancels the run, produces `stop_reason: cancelled`, and -exits 1 with guidance to add allow rules or choose another posture. - -Use `--posture auto` for autonomous CI. It allows main-agent and child tool -calls while retaining child prompt-injection defenses. Reserve `yolo` for a -disposable, isolated, single-tenant environment. +With `--permission-mode default` and `--headless`, the main agent has no +approver. Its first permission ask cancels the run, produces +`stop_reason: cancelled`, and exits 1 with guidance to add allow rules or choose +another permission mode. + +Use `--permission-mode auto` for autonomous CI. It allows main-agent and child +tool calls while retaining child prompt-injection defenses. It refuses to start +until you choose a guardrails checker with `--guardrails-model` or opt out with +`--guardrails off`. Reserve `yolo` for a disposable, isolated, single-tenant +environment. `trusted` and `trusted-accept-edits` also need `--trust-project` +or a declared trust decision, or the run refuses to start. + +The GitHub Action passes `--permission-mode auto` unless you set its +`permission-mode` input; its `posture` input is a deprecated alias. The action +passes `--guardrails-model` when its `guardrails-model` input is set and +`--guardrails off` when it is empty, so an action run with no checker model +runs with nothing inspecting tool content. For shared posture behavior, project trust, and permission-rule precedence, see [Permissions and posture](/features/security-and-execution/permissions-and-posture.md). diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index 30801b2a9a..0469989eac 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -11,12 +11,14 @@ description: Configure two independent safety controls: 1. **Permissions** decide whether a tool call is allowed, needs approval, or is - denied before it runs. + denied before it runs. A single launch-time setting, the _permission mode_, + selects how much Mecatl allows without asking. 2. **Guardrails** are an optional model-backed checker that inspects selected tool arguments and results. They are independent of the permission rules. Permissions always apply. Guardrails require an operator-configured checker -model. +model, and the allow-all permission modes require you to decide whether you +want one. For a custom authorization implementation, see [PermissionPolicy](/building/go/extension-points/permission-policy.md). @@ -25,77 +27,193 @@ For a custom authorization implementation, see Permissions and posture apply to `mecated`, `mecak8s`, `mecatequi`, and the embedded server hosted by `mecatui`. A connected `mecatui` uses the posture and -permission configuration of the remote server; local embedded-server flags do -not apply to `connect` sessions. +permission configuration of the remote server. Under `mecatui connect`, the +local `--permission-mode` flag accepts only `plan`, `default`, and +`accept-edits`, which choose the mode of the sessions that client creates. Interactive clients such as `mecatui` can answer approval requests. For headless servers and one-shot jobs, configure the permissions required by the workload before it starts. -## Choose a posture - -`--posture` selects the operator posture ladder: +## Choose a permission mode -|Posture|Behavior| -|-|-| -|`strict`|Default for interactive `mecated`; read-only calls are allowed and mutating calls use the permission rules, normally asking before they run. Project trust is not granted by the posture.| -|`trusted`|Interactive roots admit trusted project instructions and project permission allows, but mutating calls still use the normal approval rules.| -|`auto`|Enables the allow-all posture for the main agent and children while keeping deny rules and deliberately configured asks effective. Child substitution defenses remain enabled.| -|`yolo`|Extends `auto` by allowing child command substitutions, backticks, and heredoc-style substitutions that `auto` keeps behind the child safety floor. The main session also accepts external relative `../` paths for `Read`, `ListDir`, `Write`, and `Edit`. Use only for isolated, disposable, single-tenant deployments.| +Pass `--permission-mode` when you start `mecated`, `mecatui`, `mecak8s`, or +`mecatequi`. Deny rules and configured asks win in every mode, including +`yolo`. + +|Mode|Project instructions and rules|Edits|Shell and other mutations|Command substitution in subagents| +|-|-|-|-|-| +|`plan`|Only with a trust source|Denied|Denied|Not applicable, read-only| +|`default`|Only with a trust source|Ask|Ask|Ask| +|`accept-edits`|Only with a trust source|Allowed|Ask|Ask| +|`trusted`|Loaded|Ask|Ask|Ask| +|`trusted-accept-edits`|Loaded|Allowed|Ask|Ask| +|`auto`|Loaded|Allowed|Allowed|Adjudicated by a reviewer model when headless| +|`yolo`|Loaded|Allowed|Allowed|Allowed| + +"Loaded" applies to an interactive root, or to a headless root that has a trust +source. See [Project trust](#project-trust) for the trust sources and +[Headless roots and project trust](#headless-roots-and-project-trust) for how +each mode behaves without one. Use `yolo` only for isolated, disposable, +single-tenant deployments. + +A main-session external path can be addressed absolutely in any mode, subject +to its escape permission decision. Only `yolo` also serves external relative +`../` paths for `Read`, `ListDir`, `Write`, and `Edit`; in every other mode, +those relative paths remain workspace-confined even after approval. Configured +denies and asks still apply. Pseudo-filesystems (`/proc`, `/sys`, `/dev`) are +never served through these tools. Children, namespace tools, `Glob`, and `Grep` +remain confined to the workspace; symlink escapes are not a substitute for `../`. -`--yolo`, `--trust-project`, and operator-global `posture:` settings can raise -the posture tier; the highest tier wins. A project file cannot raise it. +Every root defaults to `default`, except `mecak8s`, which defaults to `auto`. +The [`mecatequi` GitHub Action](/building/ci/mecatequi.md) also passes +`auto` unless you set its `permission-mode` input. -Deployment defaults differ: `mecated` is interactive and defaults to `strict`, -while unattended `mecak8s` and `mecatequi` deployments commonly select `auto`. -Check the individual command's help before assuming a default. +```sh +# Interactive: honor this project's rules and auto-accept edits. +mecatui --workspace "$PWD" --permission-mode trusted-accept-edits -For example: +# Unattended single-tenant deployment with a guardrails checker. +mecated serve --headless --permission-mode auto --guardrails-model +``` -```sh -# Interactive, fail-closed default. -mecated serve --posture strict +To set a default for every launch, add the key to your user-global +`settings.yaml`: -# Unattended single-tenant deployment; review the trust implications first. -mecated serve --headless --posture auto +```yaml title="~/.config/mecatl/settings.yaml" +permissionMode: accept-edits ``` -Allow-all postures are refused when running as root unless the deployment -explicitly declares an isolated sandbox with `MECATL_SANDBOX=1` or -`IS_SANDBOX=1`. +An explicit `--permission-mode` flag outranks the key. Mecatl ignores a +`permissionMode:` key in a project's `.mecatl/settings.yaml` and logs a warning, +so a repository cannot choose its own permission mode. `--trust-project` +combines with any mode: it supplies project trust, and at `plan`, `default`, or +`accept-edits` it also raises the posture to `trusted`. -A main-session external path can be addressed absolutely at any posture, subject -to its escape permission decision. Only `yolo` also serves external relative -`../` paths for `Read`, `ListDir`, `Write`, and `Edit`; below `yolo`, those -relative paths remain workspace-confined even after approval. Configured denies -and asks still apply. Pseudo-filesystems (`/proc`, `/sys`, `/dev`) are never -served through these tools. Children, namespace tools, `Glob`, and `Grep` remain -confined to the workspace; symlink escapes are not a substitute for `../`. +### What a mode sets -## Choose a permission mode +Each mode sets two things with different lifetimes: -A permission mode controls one session. It works alongside the deployment -posture and configured rules. +|Mode|Posture: process-wide, fixed at startup|Session mode: where each new session starts| +|-|-|-| +|`plan`|`strict`|`plan`| +|`default`|`strict`|`default`| +|`accept-edits`|`strict`|`accept-edits`| +|`trusted`|`trusted`|`default`| +|`trusted-accept-edits`|`trusted`|`accept-edits`| +|`auto`|`auto`|`default`| +|`yolo`|`yolo`|`default`| -|Mode|Behavior| -|-|-| -|`default`|Uses the normal permission policy: read-only work is usually allowed, while operations that can mutate state normally ask first.| -|`plan`|Exposes a read-only toolset so the model can inspect the workspace and prepare a plan without changing it.| -|`accept-edits`|Automatically allows `Edit` and `Write` when they would otherwise hit only the built-in approval floor. Shell commands and other tools still use the normal policy, and configured asks and denies still win.| +The _posture_ applies to every session the server hosts and cannot change while +the process runs. The _session mode_ is only a starting point; a client can +change it for its own session. + +### Change the mode after launch In `mecatui`, press `shift+tab` to cycle the active session through **default → plan → accept-edits → default**. You can remap the `ModeSwitch` action in the client keymap or with `--keymap`; see [Keybindings](/mecatui/keybindings.md). -To select the initial mode when launching `mecatui`, use `--mode`: +Cycling changes only the session mode, never the posture. If you start in +`auto` and cycle to `plan` and back to `default`, every tool is still allowed +without asking. The `mecatui` header shows the session mode and, whenever the +posture is above `strict`, the posture as well (`trusted`, `auto`, or `yolo`). -```sh -mecatui --workspace "$PWD" --mode plan -mecatui --workspace "$PWD" --mode accept-edits -``` +`mecatui` has no control that selects `trusted`, `trusted-accept-edits`, +`auto`, or `yolo` at runtime. Those modes set the posture, so they need a +restart of the process that hosts the server: + +- With the embedded server, quit and relaunch `mecatui` with the new + `--permission-mode` value. +- Under `mecatui connect`, the server operator changes `mecated`'s + configuration and restarts it. Relaunching the client changes nothing. + +Press `?` in `mecatui` to see every mode, the two things each one sets, and the +restart that applies to your connection. + +### Check the resolved mode at startup + +Every root logs one `permission mode` line at startup. Its fields report: + +- `permission_mode`: the resolved mode. +- `posture` and `session_mode`: the two values the mode set, each with a + `_scope` field stating its lifetime. +- `guardrails_checker`: exactly one of `enforcing`, `advisory`, or `disabled`, + with a `guardrails_checker_reason` when it is not enforcing. +- `subagent_ask_reviewer`: whether the + [subagent ask reviewer](#subagents-under-auto) is on, and why. + +`mecatui` writes its startup diagnostics to its log file rather than the +terminal. + +### Deprecated flags + +`--posture`, `--yolo`, the `mecatui` `--mode` flag, and the `posture:` settings +key still work and resolve to the equivalent mode. Each logs a deprecation +warning naming the `--permission-mode` replacement, and they will be removed in +a future release. Passing `--permission-mode` together with `--posture`, +`--yolo`, or `--mode` is a startup error. `--trust-project` is not deprecated. + +## Allow-all modes need a checker decision + +`auto` and `yolo` allow every tool without asking, which leaves a guardrails +checker as the only inspection of tool content. They refuse to start until you +make one of these choices: + +- Set a checker with `--guardrails-model `. +- Bind the `guardrail` model slot, with `--model-slot guardrail=` or + `models.slots.guardrail` in `settings.yaml`. +- Run without a checker on purpose with `--guardrails off`. + +The `mecak8s` Helm chart and the `mecatequi` GitHub Action always make this +choice for you: they pass the checker model you configure, or `--guardrails off` +when you leave it empty. See [Guardrails for mecak8s](/operating/mecak8s.md#choose-a-guardrails-checker) +and the [`mecatequi` action inputs](/building/ci/mecatequi.md#headless-posture-and-permission-asks). + +At `yolo`, a configured checker is advisory only. It has no pre-tool veto, no +approve-once human ask, and no fail-closed behavior when the checker fails, so a +checker outage looks the same as a clean result. The startup line reports it as +`advisory`. Choose `auto` when you want the checker to block findings. + +## Headless roots and project trust + +A headless root never gains project trust from its permission mode. The modes +behave differently when no trust source is present: + +- `trusted` and `trusted-accept-edits` refuse to start, because project trust is + what they add. Pass `--trust-project`, add the workspace to + `trustedWorkspaces` in your user-global `settings.yaml`, or rely on a + remembered trust decision. Otherwise choose a mode that does not name trust. +- `auto` and `yolo` start and log a warning that project instructions and rules + are withheld. Tools are still allowed without asking. +- `plan`, `default`, and `accept-edits` start without loading project content. + +On an interactive root, `trusted` and `trusted-accept-edits` grant project trust +directly. + +## Subagents under auto + +Under `auto`, subagents keep the command-substitution guard that the main agent +loses. A subagent Shell command containing `$(...)`, backticks, or a subshell +that Mecatl cannot prove read-only is not run automatically, even though the +main agent would run the same command. `yolo` removes that guard for subagents +too. + +An interactive client receives these requests as ordinary approval prompts. A +headless `auto` or `yolo` deployment has nobody to ask, so the _subagent ask +reviewer_ is on by default there. The reviewer is a tool-free model that decides +a subagent permission request nobody else can answer. An approval applies only +to that request, and each decision spends tokens. + +The reviewer uses the `ask-reviewer` model slot, or the session model when the +slot is unbound. If neither resolves, subagent requests are denied and Mecatl +logs a warning naming the fix. To keep the reviewer off and deny these requests, +pass `--subagent-ask-reviewer off`. Configured deny and ask rules still win over +the reviewer. -The header displays the active mode. Changing modes does not bypass configured -permission rules or guardrails. +The reviewer is separate from the guardrails checker. The checker inspects tool +arguments and results; the reviewer decides pending subagent permission +requests. ## Approve and constrain work @@ -248,14 +366,15 @@ Project trust controls whether Mecatl admits project-provided authority: - project skills, soul, and named agents; and - the read-only child shell and workspace inspection posture. -Trust can come from an explicit operator flag, a trusted-workspace setting, an -undrifted remembered trust decision, or the interactive posture floor. A -headless root does not gain project trust merely because it uses `trusted`, -`auto`, or `yolo`; it needs an explicit trust source. +Trust can come from `--trust-project`, a `trustedWorkspaces` entry in the +user-global `settings.yaml`, an undrifted remembered trust decision, or a +`trusted`, `trusted-accept-edits`, `auto`, or `yolo` mode on an interactive +root. A headless root needs one of the first three; see +[Headless roots and project trust](#headless-roots-and-project-trust). -On an untrusted headless checkout, `--posture auto` can allow admitted tools -without loading project steering or enabling a read-only child shell. `--trust-project` asserts that you trust the repository and its `.git` metadata. +Without trust, a headless `auto` deployment still allows admitted tools, but it +loads no project steering and gives read-only subagents no Shell. ## Guardrails @@ -331,8 +450,10 @@ replacement actions are not supported. - Permission rules and guardrails are different controls: an allow does not disable guardrails, and a guardrail advisory does not change the tool's permission result. -- `--posture`, `--trust-project`, and permission configuration on a local - `mecatui` invocation do not change a remote server used through `connect`. +- `--trust-project` and permission configuration on a local `mecatui` + invocation leave a remote server used through `connect` unchanged, and + `mecatui connect` refuses a `--permission-mode` that sets a posture. The + server operator owns that server's posture. ## Next steps diff --git a/user-docs/mecatui/using-the-tui.md b/user-docs/mecatui/using-the-tui.md index 65188d1119..7ed3f17c68 100644 --- a/user-docs/mecatui/using-the-tui.md +++ b/user-docs/mecatui/using-the-tui.md @@ -236,9 +236,10 @@ for delegation behavior and the information available in `mecatui`. ## Change conversation settings -Press `shift+tab` to switch the active permission mode. See -[Choose a permission mode](/features/security-and-execution/permissions-and-posture.md#choose-a-permission-mode) -for the available modes and their behavior. +Press `shift+tab` to cycle the session through `default`, `plan`, and +`accept-edits`. The modes that change the server's posture, such as `auto`, are +set at launch with `--permission-mode`. See +[Change the mode after launch](/features/security-and-execution/permissions-and-posture.md#change-the-mode-after-launch). |Command|Result| |-|-| diff --git a/user-docs/operating/mecak8s.md b/user-docs/operating/mecak8s.md index 14e206e3a3..7dfe41c8f3 100644 --- a/user-docs/operating/mecak8s.md +++ b/user-docs/operating/mecak8s.md @@ -128,7 +128,7 @@ the values file if you need a fixed name. |Setting|Default| |-|-| |Replicas|Two| -|Posture|Headless with `auto` permissions| +|Permission mode|Headless `auto`, with no guardrails checker unless you set `guardrails.model`| |Session state|Redis| |Session ownership|Kubernetes Leases| |Filesystem|No filesystem access| @@ -139,6 +139,30 @@ Project-provided instructions, skills, agents, and read-only child Shell access still require explicit project trust. `mecak8s` does not include ACP, local JSONL storage, or the `mecated` operator subcommands. +### Choose a guardrails checker + +`auto` allows every tool without asking, so `mecak8s` refuses to start it until +you choose a guardrails checker or opt out. The chart always passes +`--permission-mode=auto` and declares the choice from `guardrails.model`: + +```yaml +guardrails: + model: +``` + +A non-empty value renders `--guardrails-model=`. The default empty value +renders `--guardrails=off`, which runs with nothing inspecting tool content. +The kill-switch also disables a `guardrail` model slot bound in mounted +settings, so name the checker here rather than relying on a slot. When you run +the `mecak8s` binary without the chart, pass `--guardrails-model` or +`--guardrails=off` yourself. + +Because `mecak8s` is headless, the subagent ask reviewer is on by default. It +uses the `ask-reviewer` model slot or the session model to decide subagent +permission requests, and each decision spends tokens. Add +`--subagent-ask-reviewer=off` to `extraArgs` to keep it off. See +[Subagents under auto](/features/security-and-execution/permissions-and-posture.md#subagents-under-auto). + ## Production Helm chart The production chart is published at diff --git a/user-docs/operating/mecated.md b/user-docs/operating/mecated.md index 0d942f788c..54dbf7e8a4 100644 --- a/user-docs/operating/mecated.md +++ b/user-docs/operating/mecated.md @@ -69,7 +69,8 @@ To retain sessions across restarts and authenticate local clients: export MECATL_AUTH_TOKEN="" mecated serve \ --store-dir ~/.local/share/mecatl/sessions \ - --posture auto + --permission-mode auto \ + --guardrails-model ``` `--log-level` accepts `debug`, `info` (default), `warn`, or `error`. Startup @@ -78,10 +79,11 @@ logs the binary version with `msg="mecated starting"`. `--store-dir` enables local JSONL persistence. The path and its ancestors must be physical directories, not symlinks. On macOS, use `/private/...` instead of a path through the `/var` symlink. `--auth-token` requires the token on every -request and can also read `MECATL_AUTH_TOKEN`. `--posture auto` permits +request and can also read `MECATL_AUTH_TOKEN`. `--permission-mode auto` permits unattended calls within configured permission rules while retaining child -prompt-injection protections. Configured Ask and Deny rules still apply; project -trust is a separate grant. +prompt-injection protections. It refuses to start without a guardrails checker +unless you pass `--guardrails off`. Configured Ask and Deny rules still apply; +project trust is a separate grant. Before binding a non-loopback address, add TLS and caller authentication. See [Secure and expose mecated](/operating/mecated/secure-and-expose.md). diff --git a/user-docs/operating/mecated/secure-and-expose.md b/user-docs/operating/mecated/secure-and-expose.md index 0f1d2ac7c2..05d4977d7c 100644 --- a/user-docs/operating/mecated/secure-and-expose.md +++ b/user-docs/operating/mecated/secure-and-expose.md @@ -48,28 +48,34 @@ and caller identifiers. See [Caller identity and OIDC](/features/security-and-execution/caller-identity.md) for the full behavior. -## Posture - -|Flag|Notes| -|-|-| -|`--posture strict`|Default approval posture; configured permission rules apply| -|`--posture trusted`|Honor a project's ALLOW rules (alias: `--trust-project`)| -|`--posture auto`|Allow unattended calls within configured rules; retain child injection defense| -|`--posture yolo`|Also disable child injection defense. Isolated single-tenant only. Refused as root without `MECATL_SANDBOX=1`| - -On a **headless** root (`--headless`), posture never raises `TrustProject`. -Explicit `--trust-project`, `trustedWorkspaces:`, or undrifted remembered trust -admits repository steering and the read-only child shell. Without a trust -source, `--posture auto` does not grant either access merely because the -directory contains `.git`. See -[Permissions and posture](/features/security-and-execution/permissions-and-posture.md#project-trust) -for the trust sources and headless behavior. - -See +## Permission mode + +`--permission-mode` defaults to `default`. It accepts `plan`, `default`, +`accept-edits`, `trusted`, `trusted-accept-edits`, `auto`, or `yolo`, and it +sets the process-wide posture and the mode new sessions start in. The +operator-global `settings.yaml` `permissionMode:` key sets the same value; the +flag overrides it. See +[Choose a permission mode](/features/security-and-execution/permissions-and-posture.md#choose-a-permission-mode) +for what each mode allows. + +`mecated` refuses to start in two cases: + +- `auto` or `yolo` with no guardrails checker. Pass `--guardrails-model`, bind + the `guardrail` model slot, or pass `--guardrails off`. +- `trusted` or `trusted-accept-edits` on a `--headless` root with no trust + source. Pass `--trust-project` or add the workspace to `trustedWorkspaces:`. + +On a headless root, `auto` and `yolo` start without a trust source but load no +project steering and give read-only subagents no Shell, because `.git` is not +vouched. Headless `auto` and `yolo` also turn on the subagent ask reviewer; pass +`--subagent-ask-reviewer off` to keep it off. See +[Subagents under auto](/features/security-and-execution/permissions-and-posture.md#subagents-under-auto). +`auto` and `yolo` are refused as root without `MECATL_SANDBOX=1`. + +`--posture`, `--yolo`, and the `posture:` key are deprecated aliases that log a +warning. See [Permissions and posture](/features/security-and-execution/permissions-and-posture.md) -for the full rule engine. Posture is read from the operator-global -`settings.yaml` (`posture:` key) and overridden by the CLI flag when both are -set. +for the full rule engine. ## Guardrails From d4185bc04e2ae9d7fd9a1268757714132708d1d5 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:45:33 +0300 Subject: [PATCH 07/48] fix(permissions): let the startup fast paths see permissionMode: ResolveAuthoritativePosture folded only the deprecated posture: key, so a settings-only permissionMode: auto or yolo skipped the early root refusal and mecatui's pre-launch warning. Build still refused, so this was a missing early exit, not a bypass. Fold the token first. Also carry the regenerated TypeScript SDK comment for the CreateSession mode change. Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/app/permission_mode_test.go | 17 +++++++++++++++++ internal/app/posture.go | 9 ++++++++- sdk/typescript/src/gen/mecatl/v1/harness_pb.ts | 4 +++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index 60e7017f83..8b4353187a 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -597,3 +597,20 @@ func TestInvariant_NoWireOrDomainSurfaceChanged(t *testing.T) { } } } + +// TestADR_0365_AuthoritativePostureFoldsPermissionModeKey pins that the cmd +// fast paths (root refusal, pre-launch WARN) see an operator-YAML-only +// permissionMode: allow-all token, not only an explicit flag. +func TestADR_0365_AuthoritativePostureFoldsPermissionModeKey(t *testing.T) { + path := filepath.Join(t.TempDir(), "operator.yaml") + if err := os.WriteFile(path, []byte("permissionMode: yolo\n"), 0o600); err != nil { + t.Fatal(err) + } + cfg := Config{Workspace: t.TempDir(), PermissionConfigs: []string{path}, Diagnostics: port.NopDiagnostics{}} + if got := ResolveAuthoritativePosture(cfg); got != PostureYolo { + t.Fatalf("authoritative posture = %s, want yolo from the permissionMode: key", got) + } + if PostureRefusalReason(ResolveAuthoritativePosture(cfg), true) == nil { + t.Fatal("a YAML-only permissionMode: yolo must hit the root/no-sandbox refusal fast path") + } +} diff --git a/internal/app/posture.go b/internal/app/posture.go index a80314f9d3..cc2504ad1e 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -275,7 +275,14 @@ func foldOperatorPosture(cfg Config) Config { // decision drive the real Build and read its structured diagnostic. func ResolveAuthoritativePosture(cfg Config) Posture { cfg.permResolver = buildPermResolver(cfg) - cfg = foldOperatorPosture(cfg) + // Fold the permission-mode token first (ADR 0365), so an operator-YAML-only + // permissionMode: auto/yolo reaches the cmd fast paths. An invalid token is + // Build's to report; the pre-check falls back to the deprecated surface. + if folded, err := foldPermissionMode(cfg); err == nil { + cfg = folded + } else { + cfg = foldOperatorPosture(cfg) + } return resolvePosture(cfg, postureNoCeiling) } diff --git a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts index b5f206da7f..e79d5724ab 100644 --- a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts +++ b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts @@ -81,7 +81,9 @@ export const LimitsSchema: GenMessage = /*@__PURE__*/ */ export type CreateSessionRequest = Message<"mecatl.v1.CreateSessionRequest"> & { /** - * mode is the permission posture; unspecified defaults to DEFAULT. + * mode is the permission posture; unspecified uses the server's configured + * default session mode, which is DEFAULT unless the operator chose a + * permission mode that starts sessions elsewhere. * * @generated from field: mecatl.v1.PermissionMode mode = 2; */ From 3a51331847aa65bd13e495af669ebd85afac01d3 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 15:56:24 +0300 Subject: [PATCH 08/48] refactor(permissions): name the checker states and bound loadProjectRules Use constants for the three checker states and the posture-named tokens, and move the project-tier posture:/permissionMode: WARNs into a helper so loadProjectRules stays under the complexity bound. Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/adapter/permconfig/resolve.go | 44 +++++++++++++++----------- internal/app/permission_mode.go | 29 +++++++++++------ 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/internal/adapter/permconfig/resolve.go b/internal/adapter/permconfig/resolve.go index 382038d14c..4a93d29a8f 100644 --- a/internal/adapter/permconfig/resolve.go +++ b/internal/adapter/permconfig/resolve.go @@ -742,24 +742,7 @@ func (r *Resolver) loadProjectRules(ws tool.WorkspaceReader) []governance.Rule { "guardrails: IGNORING a project-tier guardrails: block (operator-tier only — a project repo cannot configure/disable a security checker; set guardrails in your user-global settings.yaml or via --guardrails-model)", "file", src.path, "root", ws.Root()) } - // Posture is OPERATOR-TIER ONLY (the fail-closed core of the posture ladder): a - // project file's posture: scalar is IGNORED with a loud WARN. Honouring it would - // let a malicious repo RAISE the automation posture (e.g. posture: yolo to - // auto-run substitutions in subagents) — a security DOWNGRADE the tighten-only - // project gate forbids (it reverses here, exactly like guardrails). - if strings.TrimSpace(cfg.Posture) != "" { - r.diag.Log(context.Background(), port.LevelWarn, - "posture: IGNORING a project-tier posture: scalar (operator-tier only — a project repo cannot raise the automation posture; set permissionMode in your user-global settings.yaml or via --permission-mode)", - "file", src.path, "root", ws.Root()) - } - // PermissionMode is OPERATOR-TIER ONLY for the same reason as posture (ADR - // 0365): a repo naming its own permission mode could raise the automation - // posture. - if strings.TrimSpace(cfg.PermissionMode) != "" { - r.diag.Log(context.Background(), port.LevelWarn, - "permissionMode: IGNORING a project-tier permissionMode: scalar (operator-tier only — a project repo cannot choose its own permission mode; set permissionMode in your user-global settings.yaml or via --permission-mode)", - "file", src.path, "root", ws.Root()) - } + r.warnIgnoredProjectPermissionScalars(&cfg, src.path, ws.Root()) // ReasoningEffort is OPERATOR-TIER ONLY, for consistency with // posture: a project file's reasoning-effort: scalar is IGNORED // with a loud WARN. It is a cost/quality preference, not a security control, @@ -1089,6 +1072,31 @@ func (r *Resolver) captureGuardrails(g *GuardrailsSection) { r.operatorGuardrails = g } +// warnIgnoredProjectPermissionScalars WARNs about the operator-tier-only +// permission scalars (posture:, permissionMode:) found in a project-tier file. +// Honouring either would let a repo raise its own automation posture, so both +// are ignored; split out of loadProjectRules to keep its complexity bounded. +func (r *Resolver) warnIgnoredProjectPermissionScalars(cfg *Config, path, root string) { + // Posture is OPERATOR-TIER ONLY (the fail-closed core of the posture ladder): a + // project file's posture: scalar is IGNORED with a loud WARN. Honouring it would + // let a malicious repo RAISE the automation posture (e.g. posture: yolo to + // auto-run substitutions in subagents) — a security DOWNGRADE the tighten-only + // project gate forbids (it reverses here, exactly like guardrails). + if strings.TrimSpace(cfg.Posture) != "" { + r.diag.Log(context.Background(), port.LevelWarn, + "posture: IGNORING a project-tier posture: scalar (operator-tier only — a project repo cannot raise the automation posture; set permissionMode in your user-global settings.yaml or via --permission-mode)", + "file", path, "root", root) + } + // PermissionMode is OPERATOR-TIER ONLY for the same reason as posture (ADR + // 0365): a repo naming its own permission mode could raise the automation + // posture. + if strings.TrimSpace(cfg.PermissionMode) != "" { + r.diag.Log(context.Background(), port.LevelWarn, + "permissionMode: IGNORING a project-tier permissionMode: scalar (operator-tier only — a project repo cannot choose its own permission mode; set permissionMode in your user-global settings.yaml or via --permission-mode)", + "file", path, "root", root) + } +} + // capturePosture records the FIRST operator-tier posture: scalar seen during // construction (CLI files are parsed before user-global, so CLI wins on // first-non-empty). It is called only from loadUserRules — the operator (user- diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 5dc91cfe72..1d18ef5bf4 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -7,6 +7,7 @@ import ( "github.com/stacklok/mecatl/engine/port" "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/modelhook" "github.com/stacklok/mecatl/internal/adapter/permconfig" ) @@ -37,10 +38,11 @@ var permissionModeTable = []PermissionModeToken{ {Name: "plan", Posture: PostureStrict, SessionMode: session.ModePlan}, {Name: "default", Posture: PostureStrict, SessionMode: session.ModeDefault}, {Name: "accept-edits", Posture: PostureStrict, SessionMode: session.ModeAccept}, - {Name: "trusted", Posture: PostureTrusted, SessionMode: session.ModeDefault}, + // The three single-word tokens above strict share their posture's name. + {Name: PostureTrusted.String(), Posture: PostureTrusted, SessionMode: session.ModeDefault}, {Name: "trusted-accept-edits", Posture: PostureTrusted, SessionMode: session.ModeAccept}, - {Name: "auto", Posture: PostureAuto, SessionMode: session.ModeDefault}, - {Name: "yolo", Posture: PostureYolo, SessionMode: session.ModeDefault}, + {Name: PostureAuto.String(), Posture: PostureAuto, SessionMode: session.ModeDefault}, + {Name: PostureYolo.String(), Posture: PostureYolo, SessionMode: session.ModeDefault}, } // PermissionModeNames lists the valid tokens in table order, for help text and @@ -182,22 +184,29 @@ func (cfg Config) resolvedPermissionModeName() string { return fmt.Sprintf("posture %s with session mode %s", cfg.Posture, mode) } +// The three checker states the startup line reports (ADR 0365 AC2.6). +const ( + checkerEnforcing = "enforcing" + checkerAdvisory = "advisory" + checkerDisabled = "disabled" +) + // checkerState reports the guardrails checker as exactly one of three named // states (ADR 0365 AC2.6), plus the reason when it is disabled. func checkerState(cfg Config, configured bool) (state, reason string) { switch { case cfg.GuardrailsDisabled: - return "disabled", "kill-switch (--guardrails off)" + return checkerDisabled, "kill-switch (--guardrails off)" case !configured: - return "disabled", "no checker configured" + return checkerDisabled, "no checker configured" case cfg.Posture >= PostureYolo: - return "advisory", "demoted by posture yolo" + return checkerAdvisory, "demoted by posture yolo" } specs, _ := effectiveGuardrailSpecs(cfg) - if highestSeverityGuardrailMode(specs) == "advisory" { - return "advisory", "configured advisory" + if highestSeverityGuardrailMode(specs) == string(modelhook.ModeAdvisory) { + return checkerAdvisory, "configured advisory" } - return "enforcing", "" + return checkerEnforcing, "" } // reviewerState reports the subagent ask reviewer for the startup line. @@ -239,7 +248,7 @@ func narratePermissionMode(cfg Config, checkerConfigured bool) { if checkerReason != "" { attrs = append(attrs, "guardrails_checker_reason", checkerReason) } - if checker == "advisory" && cfg.Posture >= PostureYolo { + if checker == checkerAdvisory && cfg.Posture >= PostureYolo { attrs = append(attrs, "guardrails_checker_note", yoloCheckerAdvisoryNote) } cfg.diag().Log(context.Background(), port.LevelInfo, "permission mode", attrs...) From 3ed944429bc7c3af818ff1f77433917213633ad1 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 25 Sep 2026 16:02:08 +0300 Subject: [PATCH 09/48] docs(reference): regenerate the gRPC schema for the CreateSession mode Co-Authored-By: Claude Opus 5.5 (1M context) --- user-docs/reference/grpc-schema.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user-docs/reference/grpc-schema.md b/user-docs/reference/grpc-schema.md index 6a50c1f031..669aba5908 100644 --- a/user-docs/reference/grpc-schema.md +++ b/user-docs/reference/grpc-schema.md @@ -730,7 +730,7 @@ CreateSessionRequest opens a new session. | Field | Type | Label | Oneof | Description | |---|---|---|---|---| -| `mode` | `PermissionMode` | | | mode is the permission posture; unspecified defaults to DEFAULT. | +| `mode` | `PermissionMode` | | | mode is the permission posture; unspecified uses the server's configured default session mode, which is DEFAULT unless the operator chose a permission mode that starts sessions elsewhere. | | `limits` | `Limits` | | | limits are the optional stop conditions. | | `provider_id` | `string` | | | provider_id selects which configured provider backs this session, by its stable registry id ("openai" / "openrouter"). Empty => the agent definition's base provider when bound, otherwise the server default provider. An unknown/unavailable id is a loud InvalidArgument, never a silent fallback. The provider is FIXED for the session lifetime (reasoning-replay + byte-stable prefix are provider-private); "switch provider" = new session. Keys are NEVER on the wire — only this id. (multi-provider Phase 0, S3.) | | `model_id` | `string` | | | model_id is an opaque literal model selector, never expanded as an alias. With provider_id alone, the provider's default model applies. With neither field, an agent-bound session uses its definition's base provider/model pair; an ordinary session uses the deployment default. An id ListModels did not advertise is passed through VERBATIM. Provider and model are distinct fields, never slash-joined. model_id WITHOUT provider_id requires agent_definition_name to supply the base provider; otherwise it is InvalidArgument. | From beb409e8c00d8a2caa6f6422dc3134abd0a49012 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Mon, 5 Oct 2026 15:27:01 +0300 Subject: [PATCH 10/48] refactor(permissions): follow the ADR renumber to 0375 The plan moved the permission-mode vocabulary ADR from 0365 to 0375 after main landed its own ADR 0365. Code comments, TestADR_ names, and the generated configuration reference follow. Co-authored-by: Mecatl --- .github/actions/mecatequi/action.yml | 2 +- cmd/mecak8s/flags.go | 4 +- cmd/mecak8s/main_test.go | 4 +- cmd/mecak8s/permission_mode.go | 4 +- cmd/mecak8s/permission_mode_test.go | 10 ++-- cmd/mecak8s/telemetry_test.go | 4 +- cmd/mecated/main.go | 4 +- cmd/mecated/permission_mode.go | 6 +-- cmd/mecated/permission_mode_test.go | 12 ++--- cmd/mecatequi/flags.go | 4 +- cmd/mecatequi/permission_mode.go | 4 +- cmd/mecatequi/permission_mode_test.go | 8 ++-- cmd/mecatui/client/client.go | 2 +- cmd/mecatui/config.go | 2 +- cmd/mecatui/main.go | 2 +- cmd/mecatui/permission_mode.go | 2 +- cmd/mecatui/permission_mode_test.go | 22 ++++----- cmd/mecatui/ui/help.go | 6 +-- cmd/mecatui/ui/model.go | 2 +- ...est.go => permission_mode_adr0375_test.go} | 40 ++++++++-------- cmd/mecatui/ui/posture_badge_test.go | 2 +- cmd/mecatui/ui/view.go | 4 +- deploy/helm/mecak8s/chart_test.go | 4 +- internal/adapter/permconfig/resolve.go | 4 +- internal/adapter/permconfig/schema.go | 2 +- internal/adapter/server/default_mode_test.go | 2 +- internal/adapter/server/mapper.go | 2 +- internal/app/build.go | 12 ++--- internal/app/permission_mode.go | 16 +++---- internal/app/permission_mode_test.go | 48 +++++++++---------- internal/app/posture.go | 4 +- internal/configgen/build.go | 4 +- internal/configgen/configgen_test.go | 4 +- internal/configgen/settings.skeleton.yaml | 4 +- user-docs/reference/configuration.md | 6 +-- 35 files changed, 131 insertions(+), 131 deletions(-) rename cmd/mecatui/ui/{permission_mode_adr0365_test.go => permission_mode_adr0375_test.go} (87%) diff --git a/.github/actions/mecatequi/action.yml b/.github/actions/mecatequi/action.yml index 20b80501da..84bd7b805c 100644 --- a/.github/actions/mecatequi/action.yml +++ b/.github/actions/mecatequi/action.yml @@ -126,7 +126,7 @@ inputs: default: ${{ github.workspace }} permission-mode: description: >- - Permission mode (ADR 0365) → --permission-mode: one of plan, default, accept-edits, + Permission mode (ADR 0375) → --permission-mode: one of plan, default, accept-edits, trusted, trusted-accept-edits, auto, yolo. Empty (the input default) resolves to "auto", the documented CI mode (allow-all, child injection-defence ON), unless the deprecated `posture` input is set. "default" would CANCEL the run on the first diff --git a/cmd/mecak8s/flags.go b/cmd/mecak8s/flags.go index ed317e1c5c..e77ffcfdac 100644 --- a/cmd/mecak8s/flags.go +++ b/cmd/mecak8s/flags.go @@ -240,7 +240,7 @@ type config struct { // lets CLI out-rank the operator-global settings.yaml posture: key. posture string postureFlagSet bool - // permissionMode is the raw --permission-mode token (ADR 0365), validated at + // permissionMode is the raw --permission-mode token (ADR 0375), validated at // parse time. Empty (the default) leaves the deprecated --posture default // "auto" in force, so an unconfigured pod keeps posture auto with the default // session mode and operator YAML can still override it. @@ -827,7 +827,7 @@ func appConfig(cfg config, diag port.Diagnostics, obs observability) app.Config PermissionConfigs: cfg.permissionConfigs, Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - // Permission mode (ADR 0365): an explicit token out-ranks the deprecated + // Permission mode (ADR 0375): an explicit token out-ranks the deprecated // --posture (default auto) in app.Build's foldPermissionMode. PermissionMode: cfg.permissionMode, PermissionModeFlagSet: cfg.permissionModeFlagSet, diff --git a/cmd/mecak8s/main_test.go b/cmd/mecak8s/main_test.go index 686daa502c..ce8e0de829 100644 --- a/cmd/mecak8s/main_test.go +++ b/cmd/mecak8s/main_test.go @@ -453,7 +453,7 @@ func TestBuildOverRedisDrivesRunToCompletion(t *testing.T) { RedisAllowPlaintext: true, Interactive: false, // mecak8s headless default (Interactive=!headless) Posture: app.PostureAuto, - GuardrailsDisabled: true, // allow-all declares its checker choice (ADR 0365) + GuardrailsDisabled: true, // allow-all declares its checker choice (ADR 0375) PermissionsConventional: false, AgentsConventional: false, Diagnostics: port.NopDiagnostics{}, @@ -627,7 +627,7 @@ func TestDrainHTTPRouting(t *testing.T) { func TestServeWiresSeparateDrainListener(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", - "--guardrails=off", // the auto default must declare its checker choice (ADR 0365) + "--guardrails=off", // the auto default must declare its checker choice (ADR 0375) "--grpc-addr", freeLoopbackPort(t), "--http-addr", freeLoopbackPort(t), "--drain-addr", freeLoopbackPort(t), diff --git a/cmd/mecak8s/permission_mode.go b/cmd/mecak8s/permission_mode.go index 49b029eb35..5882a8c446 100644 --- a/cmd/mecak8s/permission_mode.go +++ b/cmd/mecak8s/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permissionModeHelp is the --permission-mode usage line (ADR 0365). It names +// permissionModeHelp is the --permission-mode usage line (ADR 0375). It names // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + @@ -46,6 +46,6 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { replacement = tok.Name } diag.Log(context.Background(), port.LevelWarn, - "--posture is DEPRECATED; use --permission-mode instead (ADR 0365)", + "--posture is DEPRECATED; use --permission-mode instead (ADR 0375)", "posture", cfg.posture, "replacement", "--permission-mode "+replacement) } diff --git a/cmd/mecak8s/permission_mode_test.go b/cmd/mecak8s/permission_mode_test.go index cf23662229..547663f69a 100644 --- a/cmd/mecak8s/permission_mode_test.go +++ b/cmd/mecak8s/permission_mode_test.go @@ -54,7 +54,7 @@ func k8sDeprecationWarnings(t *testing.T, argv ...string) []string { return out } -func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { +func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { for _, tc := range []struct{ posture, token string }{ {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, } { @@ -79,7 +79,7 @@ func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { } } -func TestADR_0365_AliasCombinationsStillResolve(t *testing.T) { +func TestADR_0375_AliasCombinationsStillResolve(t *testing.T) { // Headless root: no token grants project trust, so strict plus explicit trust // (today: trusted posture, TrustProject) must keep resolving as it does today. posture, mode, ac := k8sPair(t, "--posture", "strict", "--trust-project") @@ -96,7 +96,7 @@ func TestADR_0365_AliasCombinationsStillResolve(t *testing.T) { } } -func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { +func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { posture, mode, ac := k8sPair(t) if posture != app.PostureAuto || mode != session.ModeDefault { t.Fatalf("default mecak8s = (%s, %s), want (auto, default)", posture, mode) @@ -112,7 +112,7 @@ func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { } } -func TestADR_0365_BareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { +func TestADR_0375_BareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { build := func(argv ...string) error { cfg, err := parseFlags(argv) if err != nil { @@ -139,7 +139,7 @@ func TestADR_0365_BareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { } } -func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { +func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { _, err := parseFlags([]string{"--permission-mode", "auto", "--posture", "auto"}) if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { t.Fatalf("--permission-mode with --posture err = %v, want a pass-one startup error", err) diff --git a/cmd/mecak8s/telemetry_test.go b/cmd/mecak8s/telemetry_test.go index 2474e55999..8f9b8ac379 100644 --- a/cmd/mecak8s/telemetry_test.go +++ b/cmd/mecak8s/telemetry_test.go @@ -228,7 +228,7 @@ func TestTelemetryMetricsAddrServesPrometheus(t *testing.T) { free := freeLoopbackPort(t) cfg, err := parseFlags([]string{ "--mock", // offline: no provider key in CI - "--guardrails=off", // the auto default must declare its checker choice (ADR 0365) + "--guardrails=off", // the auto default must declare its checker choice (ADR 0375) "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--metrics-addr", free, @@ -340,7 +340,7 @@ func TestTelemetryPushesRunMetricsOnExit(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", - "--guardrails=off", // the auto default must declare its checker choice (ADR 0365) + "--guardrails=off", // the auto default must declare its checker choice (ADR 0375) "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--grpc-addr", "127.0.0.1:0", diff --git a/cmd/mecated/main.go b/cmd/mecated/main.go index 99483030d4..291e56d275 100644 --- a/cmd/mecated/main.go +++ b/cmd/mecated/main.go @@ -512,7 +512,7 @@ type config struct { // postureFlagSet is true when --posture was passed explicitly (set after parse via // fs.Visit), so composition lets CLI out-rank the settings.yaml posture: key. postureFlagSet bool - // permissionMode is the raw --permission-mode token (ADR 0365), validated at + // permissionMode is the raw --permission-mode token (ADR 0375), validated at // parse time; permissionModeFlagSet records that it was passed explicitly, so // composition (app.Build's foldPermissionMode) lets it out-rank every other // posture source. --posture and --yolo are its deprecated aliases. @@ -1342,7 +1342,7 @@ func appConfig(cfg config, sink port.EventSink, recorder port.ToolCallRecorder, // YAML-only allow-all tier cannot escape it. Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - // Permission mode (ADR 0365): the named token writes both the posture and + // Permission mode (ADR 0375): the named token writes both the posture and // the default session mode; app.Build's foldPermissionMode resolves it // ahead of the deprecated --posture/--yolo surface. PermissionMode: cfg.permissionMode, diff --git a/cmd/mecated/permission_mode.go b/cmd/mecated/permission_mode.go index f17a003112..18734340de 100644 --- a/cmd/mecated/permission_mode.go +++ b/cmd/mecated/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permissionModeHelp is the --permission-mode usage line (ADR 0365). It names +// permissionModeHelp is the --permission-mode usage line (ADR 0375). It names // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + @@ -47,12 +47,12 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { } if cfg.postureFlagSet { diag.Log(context.Background(), port.LevelWarn, - "--posture is DEPRECATED; use --permission-mode instead (ADR 0365)", + "--posture is DEPRECATED; use --permission-mode instead (ADR 0375)", "posture", cfg.posture, "replacement", "--permission-mode "+postureReplacementToken(cfg.posture)) } if cfg.yoloFlagSet { diag.Log(context.Background(), port.LevelWarn, - "--yolo is DEPRECATED; use --permission-mode yolo instead (ADR 0365)", + "--yolo is DEPRECATED; use --permission-mode yolo instead (ADR 0375)", "replacement", "--permission-mode yolo") } } diff --git a/cmd/mecated/permission_mode_test.go b/cmd/mecated/permission_mode_test.go index 27bccce5e8..091497f165 100644 --- a/cmd/mecated/permission_mode_test.go +++ b/cmd/mecated/permission_mode_test.go @@ -56,7 +56,7 @@ func deprecationWarnings(t *testing.T, argv ...string) []string { return out } -func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { +func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { cases := []struct { name string alias []string @@ -94,7 +94,7 @@ func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { } } -func TestADR_0365_AliasCombinationsStillResolve(t *testing.T) { +func TestADR_0375_AliasCombinationsStillResolve(t *testing.T) { cases := []struct { name string argv []string @@ -129,7 +129,7 @@ func TestADR_0365_AliasCombinationsStillResolve(t *testing.T) { } } -func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { +func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { for _, tc := range []struct { name string argv []string @@ -156,7 +156,7 @@ func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { } } -func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { +func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { for _, argv := range [][]string{ {"--permission-mode", "auto", "--posture", "auto"}, {"--posture", "strict", "--permission-mode", "default"}, @@ -182,7 +182,7 @@ func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { } } -func TestADR_0365_PermissionModeHitsRootRefusalFastPath(t *testing.T) { +func TestADR_0375_PermissionModeHitsRootRefusalFastPath(t *testing.T) { for _, tok := range []string{"auto", "yolo"} { cfg, err := parseFlags([]string{"--permission-mode", tok}) if err != nil { @@ -202,7 +202,7 @@ func TestADR_0365_PermissionModeHitsRootRefusalFastPath(t *testing.T) { } } -func TestADR_0365_PermissionModeHelpNamesBothHalvesAndEveryToken(t *testing.T) { +func TestADR_0375_PermissionModeHelpNamesBothHalvesAndEveryToken(t *testing.T) { for _, want := range append(app.PermissionModeNames(), "process-wide", "new sessions") { if !strings.Contains(permissionModeHelp, want) { t.Fatalf("--permission-mode help lacks %q: %s", want, permissionModeHelp) diff --git a/cmd/mecatequi/flags.go b/cmd/mecatequi/flags.go index 77ba45be74..abaf6f582a 100644 --- a/cmd/mecatequi/flags.go +++ b/cmd/mecatequi/flags.go @@ -143,7 +143,7 @@ type flags struct { // explicit --posture so composition lets CLI out-rank the settings.yaml key. posture string postureFlagSet bool - // permissionMode is the raw --permission-mode token (ADR 0365), validated at + // permissionMode is the raw --permission-mode token (ADR 0375), validated at // parse time; permissionModeFlagSet records it was passed explicitly. permissionMode string permissionModeFlagSet bool @@ -488,7 +488,7 @@ func appConfig(f flags, diag port.Diagnostics, obs observability) app.Config { Posture: app.ParsePosture(f.posture), PostureFlagSet: f.postureFlagSet, - // Permission mode (ADR 0365): an explicit token out-ranks the deprecated + // Permission mode (ADR 0375): an explicit token out-ranks the deprecated // --posture in app.Build's foldPermissionMode. PermissionMode: f.permissionMode, PermissionModeFlagSet: f.permissionModeFlagSet, diff --git a/cmd/mecatequi/permission_mode.go b/cmd/mecatequi/permission_mode.go index 5a9d1867d6..bc3598ce1c 100644 --- a/cmd/mecatequi/permission_mode.go +++ b/cmd/mecatequi/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permissionModeHelp is the --permission-mode usage line (ADR 0365). It names +// permissionModeHelp is the --permission-mode usage line (ADR 0375). It names // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + @@ -46,6 +46,6 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, f flags) { replacement = tok.Name } diag.Log(context.Background(), port.LevelWarn, - "--posture is DEPRECATED; use --permission-mode instead (ADR 0365)", + "--posture is DEPRECATED; use --permission-mode instead (ADR 0375)", "posture", f.posture, "replacement", "--permission-mode "+replacement) } diff --git a/cmd/mecatequi/permission_mode_test.go b/cmd/mecatequi/permission_mode_test.go index a0d6e9e763..22fb1eea2b 100644 --- a/cmd/mecatequi/permission_mode_test.go +++ b/cmd/mecatequi/permission_mode_test.go @@ -19,7 +19,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { +func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { for _, tc := range []struct{ posture, token string }{ {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, } { @@ -57,7 +57,7 @@ func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { } } -func TestADR_0365_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { +func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { _, err := parseFlags([]string{"--prompt", "x", "--permission-mode", "auto", "--posture", "auto"}) if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { t.Fatalf("--permission-mode with --posture err = %v, want a pass-one startup error", err) @@ -183,12 +183,12 @@ func hasPair(argv []string, flag, value string) bool { return false } -// TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0365 AC2.3 +// TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0375 AC2.3 // for the composite action and this repo's live workflow: whenever they run an // allow-all mode they pass a checker model or the explicit --guardrails off, so // the startup refusal never fires on a shipped default. It executes the action's // real bash body against a fake binary rather than grepping it. -func TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { +func TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { if _, err := exec.LookPath("bash"); err != nil { t.Skip("bash is required to execute the composite action body") } diff --git a/cmd/mecatui/client/client.go b/cmd/mecatui/client/client.go index 6416195ea9..60e053b490 100644 --- a/cmd/mecatui/client/client.go +++ b/cmd/mecatui/client/client.go @@ -721,7 +721,7 @@ func ModeFromString(s string) mecatlv1.PermissionMode { // RequestModeFromString maps the mode a client REQUESTS for a new session. It is // ModeFromString except that an empty mode means "no preference" and goes out -// UNSPECIFIED, so the server applies its own configured default mode (ADR 0365) +// UNSPECIFIED, so the server applies its own configured default mode (ADR 0375) // instead of receiving an explicit DEFAULT. func RequestModeFromString(s string) mecatlv1.PermissionMode { if s == "" { diff --git a/cmd/mecatui/config.go b/cmd/mecatui/config.go index b9423499c7..6868f787ac 100644 --- a/cmd/mecatui/config.go +++ b/cmd/mecatui/config.go @@ -238,7 +238,7 @@ type config struct { // key. Mapped onto app.Config.Posture/PostureFlagSet in embeddedConfig. posture string postureFlagSet bool - // permissionMode is the ADR 0365 named token (--permission-mode). It writes the + // permissionMode is the ADR 0375 named token (--permission-mode). It writes the // embedded server's posture half (app.Config.PermissionMode) and this client's // requested session mode. modeFlagSet/yoloFlagSet record the deprecated aliases // so the combination error and the one-per-alias deprecation WARN key on what diff --git a/cmd/mecatui/main.go b/cmd/mecatui/main.go index b7cdd46ec6..463f39b081 100644 --- a/cmd/mecatui/main.go +++ b/cmd/mecatui/main.go @@ -1592,7 +1592,7 @@ func embeddedConfig(cfg config, diag port.Diagnostics) app.Config { // escape it. Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - // ADR 0365 named token: Build resolves its posture half and puts its + // ADR 0375 named token: Build resolves its posture half and puts its // session half on the server's DefaultMode. An explicit flag out-ranks the // deprecated --posture and both YAML keys. PermissionMode: cfg.permissionMode, diff --git a/cmd/mecatui/permission_mode.go b/cmd/mecatui/permission_mode.go index dcbf0213d5..2a6f05b438 100644 --- a/cmd/mecatui/permission_mode.go +++ b/cmd/mecatui/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permission_mode.go is mecatui's half of the ADR 0365 --permission-mode flag. +// permission_mode.go is mecatui's half of the ADR 0375 --permission-mode flag. // A token names an exact (posture, session mode) pair. The posture half goes to // the embedded server's composition (app.Config.PermissionMode); the session half // is the mode this client requests for the sessions it creates. The deprecated diff --git a/cmd/mecatui/permission_mode_test.go b/cmd/mecatui/permission_mode_test.go index e2a99baf16..64c6b59108 100644 --- a/cmd/mecatui/permission_mode_test.go +++ b/cmd/mecatui/permission_mode_test.go @@ -24,10 +24,10 @@ func deprecationLines(cfg config) []string { return strings.Split(out, "\n") } -// TestADR_0365_DeprecatedAliasesStillResolve pins AC6.1 for mecatui: --mode, +// TestADR_0375_DeprecatedAliasesStillResolve pins AC6.1 for mecatui: --mode, // --posture, and --yolo resolve exactly as before and each emits exactly one // deprecation WARN naming --permission-mode. --trust-project is not deprecated. -func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { +func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { cases := []struct { name string args []string @@ -94,10 +94,10 @@ func TestADR_0365_DeprecatedAliasesStillResolve(t *testing.T) { }) } -// TestADR_0365_PermissionModeConflictsWithAliases pins that --permission-mode +// TestADR_0375_PermissionModeConflictsWithAliases pins that --permission-mode // combined with any deprecated alias is a startup error telling the operator to // pass one, and that an unknown token fails fast naming the valid set. -func TestADR_0365_PermissionModeConflictsWithAliases(t *testing.T) { +func TestADR_0375_PermissionModeConflictsWithAliases(t *testing.T) { for _, alias := range [][]string{{"--mode", "plan"}, {"--posture", "auto"}, {"--yolo"}} { args := append([]string{"--mock", "--workspace", "/abs", "--permission-mode", "plan"}, alias...) _, _, err := parseTransportFlagsTest(t, modeLocal, args) @@ -117,10 +117,10 @@ func TestADR_0365_PermissionModeConflictsWithAliases(t *testing.T) { } } -// TestADR_0365_ConnectRefusesPostureHalf pins the connect behaviour: the session +// TestADR_0375_ConnectRefusesPostureHalf pins the connect behaviour: the session // half of a token applies to this client's sessions, while a non-strict posture // half is refused because the posture belongs to the remote server. -func TestADR_0365_ConnectRefusesPostureHalf(t *testing.T) { +func TestADR_0375_ConnectRefusesPostureHalf(t *testing.T) { _, cfg, err := parseTransportFlagsTest(t, modeConnect, []string{"--permission-mode", "accept-edits"}) if err != nil { t.Fatalf("session-only token under connect: %v", err) @@ -139,9 +139,9 @@ func TestADR_0365_ConnectRefusesPostureHalf(t *testing.T) { } } -// TestADR_0365_VocabularyMatchesComposition keeps the TUI's display copy of the +// TestADR_0375_VocabularyMatchesComposition keeps the TUI's display copy of the // token table identical to the composition layer's contract. -func TestADR_0365_VocabularyMatchesComposition(t *testing.T) { +func TestADR_0375_VocabularyMatchesComposition(t *testing.T) { vocab := ui.PermissionModeVocabulary() names := app.PermissionModeNames() if len(vocab) != len(names) { @@ -163,11 +163,11 @@ func TestADR_0365_VocabularyMatchesComposition(t *testing.T) { } } -// TestADR_0365_DefaultsReproduceCurrentBehaviour pins AC6.3 for mecatui end to +// TestADR_0375_DefaultsReproduceCurrentBehaviour pins AC6.3 for mecatui end to // end: the parsed flags build the real embedded server, the real client creates a // session through the real sessionAdapter, and the server-reported posture and -// session mode match what mecatui produced before ADR 0365. -func TestADR_0365_DefaultsReproduceCurrentBehaviour(t *testing.T) { +// session mode match what mecatui produced before ADR 0375. +func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { cases := []struct { name string args []string diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 5afe10e8a4..470916b0fd 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -159,7 +159,7 @@ func helpBody(th theme.Theme, caps client.Capabilities, hk helpKeys) string { // helpBody renders the overlay body for this model's transport: the permission // mode section's restart guidance differs between the embedded server and -// `mecatui connect` (ADR 0365). +// `mecatui connect` (ADR 0375). func (m Model) helpBody() string { return helpBodyFor(m.deps.Theme, m.caps, m.helpKeyMarkings(), m.deps.Embedded) } @@ -310,7 +310,7 @@ func helpBodyFor(th theme.Theme, caps client.Capabilities, hk helpKeys, embedded return b.String() } -// PermissionModeEntry is one row of the ADR 0365 permission-mode vocabulary as +// PermissionModeEntry is one row of the ADR 0375 permission-mode vocabulary as // the TUI displays it: the token, the process-wide posture it sets, and the // session mode new sessions start in (the TUI spelling). type PermissionModeEntry struct { @@ -337,7 +337,7 @@ func PermissionModeVocabulary() []PermissionModeEntry { // writeHelpPermissionModes lists every permission-mode token with its two // halves, states that the posture half is process-wide while the session half is // only a new-session default, that cycling the session mode never changes the -// posture, and whose restart a posture change needs (ADR 0365, AC5.2/AC5.5). +// posture, and whose restart a posture change needs (ADR 0375, AC5.2/AC5.5). // Runtime selection of a posture from the TUI is deliberately not offered. func writeHelpPermissionModes(b *strings.Builder, th theme.Theme, hk helpKeys, embedded bool) { b.WriteString("\n" + th.Style("toolName").Render("Permission modes (--permission-mode, set at launch)") + "\n") diff --git a/cmd/mecatui/ui/model.go b/cmd/mecatui/ui/model.go index 33fee06436..e3d4468ff3 100644 --- a/cmd/mecatui/ui/model.go +++ b/cmd/mecatui/ui/model.go @@ -295,7 +295,7 @@ type Deps struct { Mode string Model string // ModeServerDefault asks the server to choose the first session's permission - // mode (ADR 0365): no --permission-mode or --mode was given, so the create + // mode (ADR 0375): no --permission-mode or --mode was given, so the create // carries an unspecified mode and the server's configured default applies // (embedded: the operator's permissionMode: key; connect: the remote server's // own default). The created session's mode is read back with GetSession, so the diff --git a/cmd/mecatui/ui/permission_mode_adr0365_test.go b/cmd/mecatui/ui/permission_mode_adr0375_test.go similarity index 87% rename from cmd/mecatui/ui/permission_mode_adr0365_test.go rename to cmd/mecatui/ui/permission_mode_adr0375_test.go index 315bd099e3..338f3deb72 100644 --- a/cmd/mecatui/ui/permission_mode_adr0365_test.go +++ b/cmd/mecatui/ui/permission_mode_adr0375_test.go @@ -12,8 +12,8 @@ import ( "github.com/stacklok/mecatl/cmd/mecatui/theme" ) -// adr0365Model is a live model bound to a session whose server reports posture. -func adr0365Model(t *testing.T, conv *fakeConv, posture string, embedded bool) Model { +// adr0375Model is a live model bound to a session whose server reports posture. +func adr0375Model(t *testing.T, conv *fakeConv, posture string, embedded bool) Model { t.Helper() m := newTestModelFromDeps(Deps{ Session: conv, @@ -46,12 +46,12 @@ func cycleMode(t *testing.T, m Model) Model { return applyAll(m, cmd()) } -// TestADR_0365_ModeSwitchCycleUnchanged pins AC5.1: the session mode cycle offers -// exactly the three session modes in the same order as before ADR 0365. No +// TestADR_0375_ModeSwitchCycleUnchanged pins AC5.1: the session mode cycle offers +// exactly the three session modes in the same order as before ADR 0375. No // posture-bearing token becomes reachable from the keybinding. -func TestADR_0365_ModeSwitchCycleUnchanged(t *testing.T) { +func TestADR_0375_ModeSwitchCycleUnchanged(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0365Model(t, conv, postureStrict, true) + m := adr0375Model(t, conv, postureStrict, true) want := []string{"plan", "accept-edits", "default", "plan"} for range want { m = cycleMode(t, m) @@ -65,16 +65,16 @@ func TestADR_0365_ModeSwitchCycleUnchanged(t *testing.T) { } } -// TestADR_0365_HelpOverlayShowsVocabularyAndScopeSplit pins AC5.2: every token is +// TestADR_0375_HelpOverlayShowsVocabularyAndScopeSplit pins AC5.2: every token is // listed with its posture half marked process-wide and its session half marked as // the new-session default, with the exact invocation and the statement that // cycling the session mode never changes the posture half. -func TestADR_0365_HelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { +func TestADR_0375_HelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0365Model(t, conv, postureStrict, true) + m := adr0375Model(t, conv, postureStrict, true) body := stripANSIstr(m.helpBody()) - // The ADR 0365 table, written out independently of PermissionModeVocabulary. + // The ADR 0375 table, written out independently of PermissionModeVocabulary. want := []struct{ token, posture, session string }{ {"plan", "strict", "plan"}, {"default", "strict", "default"}, @@ -111,10 +111,10 @@ func TestADR_0365_HelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { } } -// TestADR_0365_HeaderShowsPostureWhenAboveStrict pins AC5.3: the header shows the +// TestADR_0375_HeaderShowsPostureWhenAboveStrict pins AC5.3: the header shows the // session mode, and a posture badge for every tier above strict (trusted now // included), sourced from the server-reported caps.Posture. -func TestADR_0365_HeaderShowsPostureWhenAboveStrict(t *testing.T) { +func TestADR_0375_HeaderShowsPostureWhenAboveStrict(t *testing.T) { cases := []struct { posture string badge string // "" = no badge @@ -127,7 +127,7 @@ func TestADR_0365_HeaderShowsPostureWhenAboveStrict(t *testing.T) { for _, tc := range cases { t.Run(tc.posture, func(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0365Model(t, conv, tc.posture, true) + m := adr0375Model(t, conv, tc.posture, true) header := stripANSIstr(m.renderHeader()) if got := statusMode(m); got != "default" { t.Errorf("status mode = %q, want default", got) @@ -146,12 +146,12 @@ func TestADR_0365_HeaderShowsPostureWhenAboveStrict(t *testing.T) { } } -// TestADR_0365_HeaderKeepsPostureAcrossModeCycle pins AC5.4: under auto, cycling +// TestADR_0375_HeaderKeepsPostureAcrossModeCycle pins AC5.4: under auto, cycling // the session mode through plan and back to default keeps the auto badge on every // frame, including the pending frame before the server confirms each switch. -func TestADR_0365_HeaderKeepsPostureAcrossModeCycle(t *testing.T) { +func TestADR_0375_HeaderKeepsPostureAcrossModeCycle(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0365Model(t, conv, postureAuto, true) + m := adr0375Model(t, conv, postureAuto, true) assertAuto := func(step, wantMode string) { t.Helper() header := stripANSIstr(m.renderHeader()) @@ -175,13 +175,13 @@ func TestADR_0365_HeaderKeepsPostureAcrossModeCycle(t *testing.T) { } } -// TestADR_0365_HelpOverlayNamesWhoseRestart pins AC5.5: the embedded server's +// TestADR_0375_HelpOverlayNamesWhoseRestart pins AC5.5: the embedded server's // help gives the mecatui relaunch invocation; under `mecatui connect` it names // the server operator's mecated restart and offers no local invocation. -func TestADR_0365_HelpOverlayNamesWhoseRestart(t *testing.T) { +func TestADR_0375_HelpOverlayNamesWhoseRestart(t *testing.T) { render := func(embedded bool) string { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0365Model(t, conv, postureAuto, embedded) + m := adr0375Model(t, conv, postureAuto, embedded) return stripANSIstr(m.helpBody()) } embedded := render(true) @@ -200,7 +200,7 @@ func TestADR_0365_HelpOverlayNamesWhoseRestart(t *testing.T) { } } -// TestModeServerDefaultRequestsUnspecifiedAndReadsBack pins the ADR 0365 session +// TestModeServerDefaultRequestsUnspecifiedAndReadsBack pins the ADR 0375 session // half under ModeServerDefault: the first create requests no mode, so the server's // default applies, and the header shows the mode the server reports rather than // guessing "default". diff --git a/cmd/mecatui/ui/posture_badge_test.go b/cmd/mecatui/ui/posture_badge_test.go index c7f533dd30..0872dd302e 100644 --- a/cmd/mecatui/ui/posture_badge_test.go +++ b/cmd/mecatui/ui/posture_badge_test.go @@ -13,7 +13,7 @@ import ( // TestPostureBadgeShownForAutoYolo asserts the header renders the auto/yolo chrome // badge when the server reports an allow-all posture, the quieter trusted badge for -// trusted (ADR 0365), and NO badge for strict (and an empty/older-server posture) — +// trusted (ADR 0375), and NO badge for strict (and an empty/older-server posture) — // the goldens-stability guarantee. Under // MECATUI_NO_EMOJI the yolo badge is the clean " YOLO " pill with NO lightning bolt and // NO VS16; auto is "⚠ auto". The badge is sourced from caps.Posture (SessionReadyMsg), diff --git a/cmd/mecatui/ui/view.go b/cmd/mecatui/ui/view.go index 69f17bec14..27147f3527 100644 --- a/cmd/mecatui/ui/view.go +++ b/cmd/mecatui/ui/view.go @@ -209,7 +209,7 @@ const yoloBoltPrefix = "⚡️ " // fit/shed math. It surfaces the SERVER-WIDE posture (m.caps.Posture) whenever it is // above strict — strict/unknown render NO badge, so the steady-state frame and the // goldens stay byte-identical. It is DISTINCT from the per-session `mode` segment, and a -// session-mode cycle never changes it (ADR 0365). +// session-mode cycle never changes it (ADR 0375). // // Tiers: // - trusted → warning-styled inline text "trusted". @@ -236,7 +236,7 @@ func (m Model) postureBadgeRender() (styled string, plainWidth int) { } return pill, w case postureTrusted: - // Above strict (ADR 0365, AC5.3): the project's rules and instructions are + // Above strict (ADR 0375, AC5.3): the project's rules and instructions are // honoured process-wide, so the header must not read as a plain default // session. Warning-styled text, no glyph, quieter than auto's. return m.deps.Theme.Style("warning").Render(trustedBadgeText), lipgloss.Width(trustedBadgeText) diff --git a/deploy/helm/mecak8s/chart_test.go b/deploy/helm/mecak8s/chart_test.go index e6ca71f601..00c58d8982 100644 --- a/deploy/helm/mecak8s/chart_test.go +++ b/deploy/helm/mecak8s/chart_test.go @@ -3074,12 +3074,12 @@ mcp: } } -// TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0365 AC2.3 for +// TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0375 AC2.3 for // the chart: it runs mecak8s in the allow-all auto permission mode, and mecak8s // refuses that mode without a checker, so every render must declare the checker // choice. An empty guardrails.model is the explicit unsupervised --guardrails=off; // a set model becomes --guardrails-model and never carries the kill-switch. -func TestADR_0365_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { +func TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { cases := []struct { name string extra []string diff --git a/internal/adapter/permconfig/resolve.go b/internal/adapter/permconfig/resolve.go index 4a93d29a8f..c58b47b317 100644 --- a/internal/adapter/permconfig/resolve.go +++ b/internal/adapter/permconfig/resolve.go @@ -139,7 +139,7 @@ type Resolver struct { // files) out-ranks user-global (first-non-empty keeps CLI). operatorPosture string - // operatorPermissionMode is the OPERATOR-TIER permissionMode: token (ADR 0365), + // operatorPermissionMode is the OPERATOR-TIER permissionMode: token (ADR 0375), // captured exactly like operatorPosture: user-global + CLI tiers only, CLI // first-non-empty wins, a project-tier occurrence is ignored with a WARN. operatorPermissionMode string @@ -1088,7 +1088,7 @@ func (r *Resolver) warnIgnoredProjectPermissionScalars(cfg *Config, path, root s "file", path, "root", root) } // PermissionMode is OPERATOR-TIER ONLY for the same reason as posture (ADR - // 0365): a repo naming its own permission mode could raise the automation + // 0375): a repo naming its own permission mode could raise the automation // posture. if strings.TrimSpace(cfg.PermissionMode) != "" { r.diag.Log(context.Background(), port.LevelWarn, diff --git a/internal/adapter/permconfig/schema.go b/internal/adapter/permconfig/schema.go index d7a102eeaa..8184d39ccb 100644 --- a/internal/adapter/permconfig/schema.go +++ b/internal/adapter/permconfig/schema.go @@ -165,7 +165,7 @@ type Config struct { // keeps the CLI/default). The composition layer parses the string; permconfig only // reads the scalar. Posture string `yaml:"posture"` - // PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0365: + // PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0375: // plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets // the posture and the default session mode together and supersedes the // deprecated posture: key. Like Posture it is honoured ONLY from the diff --git a/internal/adapter/server/default_mode_test.go b/internal/adapter/server/default_mode_test.go index e9b42466b4..1755d0d17e 100644 --- a/internal/adapter/server/default_mode_test.go +++ b/internal/adapter/server/default_mode_test.go @@ -17,7 +17,7 @@ import ( // TestGRPCCreateSessionUnspecifiedModeUsesServerDefault pins that a gRPC // CreateSession leaving mode UNSPECIFIED starts in the server's configured -// DefaultMode (the session half of the operator's permission mode, ADR 0365), +// DefaultMode (the session half of the operator's permission mode, ADR 0375), // while an explicit mode still wins. func TestGRPCCreateSessionUnspecifiedModeUsesServerDefault(t *testing.T) { llm := mockllm.New() diff --git a/internal/adapter/server/mapper.go b/internal/adapter/server/mapper.go index 92c5686044..e88569e865 100644 --- a/internal/adapter/server/mapper.go +++ b/internal/adapter/server/mapper.go @@ -1408,7 +1408,7 @@ func modeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { // createModeFromProto maps a CreateSession mode. Unlike modeFromProto, an // UNSPECIFIED mode stays empty so Service.createSession applies the server's // configured DefaultMode (the session half of the operator's permission mode, -// ADR 0365), matching the HTTP create path. +// ADR 0375), matching the HTTP create path. func createModeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { if m == mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { return "" diff --git a/internal/app/build.go b/internal/app/build.go index 45d9fad694..c4d553d196 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -1081,7 +1081,7 @@ type Config struct { // (CLI out-ranks YAML) and resolvePosture WARNs if an alias raised above the // explicit value. Set by the cmd mains alongside Posture. PostureFlagSet bool - // PermissionMode is the raw --permission-mode token (ADR 0365), meaningful only + // PermissionMode is the raw --permission-mode token (ADR 0375), meaningful only // when PermissionModeFlagSet. foldPermissionMode resolves it (or the // operator-tier permissionMode: key) into Posture + DefaultSessionMode; an // unknown token is a Build error naming the valid set. @@ -1098,7 +1098,7 @@ type Config struct { // foldPermissionMode; empty when only the deprecated surface was used. permissionModeName string // askReviewerDefaultOn is set by resolveAskReviewerDefault when the headless - // allow-all default engages the subagent ask reviewer (ADR 0365 decision 6). + // allow-all default engages the subagent ask reviewer (ADR 0375 decision 6). askReviewerDefaultOn bool // askReviewerOptOut records an explicit --subagent-ask-reviewer off. askReviewerOptOut bool @@ -1725,7 +1725,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.TrustProject = trust.Trusted narratePosture(cfg.diag(), cfg.Posture, cfg.TrustProject) narrateTrust(cfg.diag(), trust, cfg.Workspace) - // Headless admission gate (ADR 0365): after the trust fold, so every + // Headless admission gate (ADR 0375): after the trust fold, so every // legitimate trust source satisfies it. if err := headlessTrustRefusal(cfg); err != nil { return nil, err @@ -2092,7 +2092,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.guardrailModel = guardrailModel cfg.guardrailSource = guardrailSrc cfg.guardrailConfigured = guardrailConfigured - // Allow-all admission gate (ADR 0365): the checker truth is the SAME the + // Allow-all admission gate (ADR 0375): the checker truth is the SAME the // posture line and the live checker use (the binding, else the resolver). checkerConfigured := guardrailConfigured if !checkerConfigured { @@ -2448,7 +2448,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { mcpStatus = assets.mcpReconciler.statusSnapshot } svcCfg := server.Config{ - // The session half of the permission-mode token (ADR 0365): the mode a + // The session half of the permission-mode token (ADR 0375): the mode a // CreateSession that leaves mode unspecified starts in. Empty keeps the // server's own ModeDefault. DefaultMode: cfg.DefaultSessionMode, @@ -7488,7 +7488,7 @@ func askAdjudicatorDeps(cfg Config, provReg *providerRegistry, provider port.LLM // The --subagent-ask-reviewer flag STAYS the enable gate: a slot alone does // NOT turn the reviewer on (a slot only chooses the model for a reviewer the // operator already enabled). Empty flag ⇒ reviewer off, byte-identical — - // except the ADR 0365 headless allow-all default (askReviewerDefaultOn), + // except the ADR 0375 headless allow-all default (askReviewerDefaultOn), // which resolves through the slot, then the parent model, below. return agent.Deps{}, false } diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 1d18ef5bf4..b527f86f52 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -12,7 +12,7 @@ import ( ) // permission_mode.go is the COMPOSITION-LAYER named permission-mode vocabulary -// (ADR 0365). A token is an operator shorthand that writes an exact pair of +// (ADR 0375). A token is an operator shorthand that writes an exact pair of // EXISTING values: the process-wide Posture and the default session // PermissionMode (server.Config.DefaultMode). It introduces no third source of // permission state: the table below is the whole mechanism, and it is a lookup, @@ -31,7 +31,7 @@ type PermissionModeToken struct { SessionMode session.PermissionMode } -// permissionModeTable is the ADR 0365 contract. Redundant products (an +// permissionModeTable is the ADR 0375 contract. Redundant products (an // accept-edits variant of auto or yolo) are deliberately absent: allow-all // already permits edits. var permissionModeTable = []PermissionModeToken{ @@ -120,7 +120,7 @@ func foldPermissionMode(cfg Config) (Config, error) { return cfg, nil } -// checkerRefusal is the allow-all admission gate (ADR 0365 decision 4). A +// checkerRefusal is the allow-all admission gate (ADR 0375 decision 4). A // posture that waives the built-in mutate-ask floor leaves the guardrails // checker as the only inspection of tool content, so starting one with no // checker and no explicit kill-switch is refused. It keys on the RESOLVED @@ -143,7 +143,7 @@ func checkerRefusal(cfg Config, checkerConfigured bool) error { // refusal and the startup line so they cannot disagree. const yoloCheckerAdvisoryNote = "At yolo a configured checker is observability-only: it has no pre-tool veto, no approve-once human ask, and no fail-closed on checker failure, so a checker outage looks the same as a clean result" -// headlessTrustRefusal is the headless admission gate (ADR 0365 decision 5). +// headlessTrustRefusal is the headless admission gate (ADR 0375 decision 5). // It runs AFTER resolveTrust, so any legitimate trust source satisfies it, and // applies only to the trust-naming posture: trust is not auto's or yolo's // defining increment, so those WARN instead (narrateWithheldTrust). @@ -184,7 +184,7 @@ func (cfg Config) resolvedPermissionModeName() string { return fmt.Sprintf("posture %s with session mode %s", cfg.Posture, mode) } -// The three checker states the startup line reports (ADR 0365 AC2.6). +// The three checker states the startup line reports (ADR 0375 AC2.6). const ( checkerEnforcing = "enforcing" checkerAdvisory = "advisory" @@ -192,7 +192,7 @@ const ( ) // checkerState reports the guardrails checker as exactly one of three named -// states (ADR 0365 AC2.6), plus the reason when it is disabled. +// states (ADR 0375 AC2.6), plus the reason when it is disabled. func checkerState(cfg Config, configured bool) (state, reason string) { switch { case cfg.GuardrailsDisabled: @@ -227,7 +227,7 @@ func reviewerState(cfg Config) string { // narratePermissionMode is the ONE build-once line reporting the resolved token, // both halves it set with their lifetimes, and the checker and reviewer states -// as separately scannable items (ADR 0365 AC5.6). The reviewer and the checker +// as separately scannable items (ADR 0375 AC5.6). The reviewer and the checker // are different mechanisms and are named separately; neither is described in // the other's terms. func narratePermissionMode(cfg Config, checkerConfigured bool) { @@ -265,7 +265,7 @@ func isAskReviewerOptOut(s string) bool { } // resolveAskReviewerDefault decides whether the headless subagent ask reviewer -// is on by default (ADR 0365 decision 6): headless (no human approver), an +// is on by default (ADR 0375 decision 6): headless (no human approver), an // allow-all posture, no explicit reviewer model, and no explicit opt-out. It // resolves its model through the existing ask-reviewer slot with the // parent-model fallback; when neither resolves, behaviour stays today's diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index 8b4353187a..71b93483e2 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -15,7 +15,7 @@ import ( "github.com/stacklok/mecatl/internal/adapter/permconfig" ) -// permissionModeCfg is the offline Build fixture for the ADR 0365 tests: an +// permissionModeCfg is the offline Build fixture for the ADR 0375 tests: an // explicit --permission-mode token over the mock provider. func permissionModeCfg(t *testing.T, token string, diag port.Diagnostics) Config { t.Helper() @@ -41,7 +41,7 @@ func builtDefaultSessionMode(t *testing.T, built *Built) session.PermissionMode return sess.Mode } -func TestADR_0365_TokenTableResolvesExactPairs(t *testing.T) { +func TestADR_0375_TokenTableResolvesExactPairs(t *testing.T) { want := map[string]struct { posture Posture mode session.PermissionMode @@ -96,7 +96,7 @@ func TestADR_0365_TokenTableResolvesExactPairs(t *testing.T) { } } -func TestADR_0365_TrustedKeepsCurrentMeaning(t *testing.T) { +func TestADR_0375_TrustedKeepsCurrentMeaning(t *testing.T) { cfg := permissionModeCfg(t, "trusted", port.NopDiagnostics{}) legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, Posture: PostureTrusted, PostureFlagSet: true} for name, c := range map[string]Config{"token": cfg, "--posture trusted": legacy} { @@ -114,7 +114,7 @@ func TestADR_0365_TrustedKeepsCurrentMeaning(t *testing.T) { } } -func TestADR_0365_TrustedAcceptEditsIsNameable(t *testing.T) { +func TestADR_0375_TrustedAcceptEditsIsNameable(t *testing.T) { built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", port.NopDiagnostics{})) if err != nil { t.Fatalf("Build: %v", err) @@ -128,7 +128,7 @@ func TestADR_0365_TrustedAcceptEditsIsNameable(t *testing.T) { } } -func TestADR_0365_AllowAllTokenRequiresChecker(t *testing.T) { +func TestADR_0375_AllowAllTokenRequiresChecker(t *testing.T) { for _, token := range []string{"auto", "yolo"} { _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) if err == nil { @@ -157,7 +157,7 @@ func TestADR_0365_AllowAllTokenRequiresChecker(t *testing.T) { } } -func TestADR_0365_CheckerRefusalNamesEveryFix(t *testing.T) { +func TestADR_0375_CheckerRefusalNamesEveryFix(t *testing.T) { _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "auto", port.NopDiagnostics{})) if err == nil { t.Fatal("auto with no checker must refuse") @@ -169,7 +169,7 @@ func TestADR_0365_CheckerRefusalNamesEveryFix(t *testing.T) { } } -func TestADR_0365_GateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { +func TestADR_0375_GateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { properties := []string{"pre-tool veto", "approve-once human ask", "fail-closed"} _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "yolo", port.NopDiagnostics{})) @@ -201,7 +201,7 @@ func TestADR_0365_GateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { } } -func TestADR_0365_NonAllowAllTokensRequireNoChecker(t *testing.T) { +func TestADR_0375_NonAllowAllTokensRequireNoChecker(t *testing.T) { for _, token := range []string{"plan", "default", "accept-edits", "trusted", "trusted-accept-edits"} { built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) if err != nil { @@ -211,7 +211,7 @@ func TestADR_0365_NonAllowAllTokensRequireNoChecker(t *testing.T) { } } -func TestADR_0365_StartupLineNamesCheckerState(t *testing.T) { +func TestADR_0375_StartupLineNamesCheckerState(t *testing.T) { cases := []struct { name string cfg Config @@ -251,7 +251,7 @@ func headlessCfg(t *testing.T, token string, diag port.Diagnostics) Config { return cfg } -func TestADR_0365_HeadlessTrustTokenRefused(t *testing.T) { +func TestADR_0375_HeadlessTrustTokenRefused(t *testing.T) { for _, token := range []string{"trusted", "trusted-accept-edits"} { _, err := buildIsolated(t, context.Background(), headlessCfg(t, token, port.NopDiagnostics{})) if err == nil { @@ -265,7 +265,7 @@ func TestADR_0365_HeadlessTrustTokenRefused(t *testing.T) { } } -func TestADR_0365_HeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { +func TestADR_0375_HeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { t.Run("explicit --trust-project", func(t *testing.T) { cfg := headlessCfg(t, "trusted", port.NopDiagnostics{}) cfg.TrustProject = true @@ -289,7 +289,7 @@ func TestADR_0365_HeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { }) } -func TestADR_0365_HeadlessAllowAllStartsWithoutTrust(t *testing.T) { +func TestADR_0375_HeadlessAllowAllStartsWithoutTrust(t *testing.T) { for _, token := range []string{"auto", "yolo"} { rec := slogdiagBuffer(t) cfg := headlessCfg(t, token, rec.diag) @@ -308,7 +308,7 @@ func TestADR_0365_HeadlessAllowAllStartsWithoutTrust(t *testing.T) { } } -func TestADR_0365_InteractiveTrustTokenGrantsTrust(t *testing.T) { +func TestADR_0375_InteractiveTrustTokenGrantsTrust(t *testing.T) { withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted", rec.diag)) @@ -324,7 +324,7 @@ func TestADR_0365_InteractiveTrustTokenGrantsTrust(t *testing.T) { } } -func TestADR_0365_AllowAllNarratesSubagentAsymmetry(t *testing.T) { +func TestADR_0375_AllowAllNarratesSubagentAsymmetry(t *testing.T) { rec := slogdiagBuffer(t) cfg := permissionModeCfg(t, "auto", rec.diag) cfg.GuardrailsDisabled = true @@ -347,7 +347,7 @@ func headlessAllowAll(t *testing.T, diag port.Diagnostics) Config { return cfg } -func TestADR_0365_HeadlessAllowAllDefaultsReviewerOn(t *testing.T) { +func TestADR_0375_HeadlessAllowAllDefaultsReviewerOn(t *testing.T) { rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), headlessAllowAll(t, rec.diag)) if err != nil { @@ -375,7 +375,7 @@ func TestADR_0365_HeadlessAllowAllDefaultsReviewerOn(t *testing.T) { } } -func TestADR_0365_ReviewerDefaultIsOptOutAndNarrated(t *testing.T) { +func TestADR_0375_ReviewerDefaultIsOptOutAndNarrated(t *testing.T) { rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), headlessAllowAll(t, rec.diag)) if err != nil { @@ -405,7 +405,7 @@ func TestADR_0365_ReviewerDefaultIsOptOutAndNarrated(t *testing.T) { } } -func TestADR_0365_ReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { +func TestADR_0375_ReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { rec := slogdiagBuffer(t) cfg := resolveAskReviewerDefault(Config{Posture: PostureAuto, Diagnostics: rec.diag}) if cfg.askReviewerDefaultOn { @@ -419,7 +419,7 @@ func TestADR_0365_ReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { } } -func TestADR_0365_ReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { +func TestADR_0375_ReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { for name, cfg := range map[string]Config{ "interactive auto": {Posture: PostureAuto, Interactive: true, Model: "m"}, "headless strict": {Posture: PostureStrict, Model: "m"}, @@ -432,7 +432,7 @@ func TestADR_0365_ReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { } } -func TestADR_0365_ReviewerAndCheckerNarratedSeparately(t *testing.T) { +func TestADR_0375_ReviewerAndCheckerNarratedSeparately(t *testing.T) { rec := slogdiagBuffer(t) cfg := headlessCfg(t, "auto", rec.diag) cfg.GuardrailsModel = "mock-checker" @@ -456,7 +456,7 @@ func TestADR_0365_ReviewerAndCheckerNarratedSeparately(t *testing.T) { } } -func TestADR_0365_StartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing.T) { +func TestADR_0375_StartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing.T) { rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", rec.diag)) if err != nil { @@ -482,7 +482,7 @@ func TestADR_0365_StartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing } } -func TestADR_0365_PermissionModeIsOperatorTierOnly(t *testing.T) { +func TestADR_0375_PermissionModeIsOperatorTierOnly(t *testing.T) { operatorFile := func(t *testing.T, token string) string { t.Helper() path := filepath.Join(t.TempDir(), "operator.yaml") @@ -574,7 +574,7 @@ func TestADR_0365_PermissionModeIsOperatorTierOnly(t *testing.T) { } // TestInvariant_NoWireOrDomainSurfaceChanged pins that the vocabulary added no -// session-selectable value (ADR 0365 decision 3): the domain keeps its three +// session-selectable value (ADR 0375 decision 3): the domain keeps its three // modes with their strings, the proto enum keeps its four values, and an old // snapshot's mode string still round-trips. `task api:check` covers the engine // API surface itself. @@ -598,10 +598,10 @@ func TestInvariant_NoWireOrDomainSurfaceChanged(t *testing.T) { } } -// TestADR_0365_AuthoritativePostureFoldsPermissionModeKey pins that the cmd +// TestADR_0375_AuthoritativePostureFoldsPermissionModeKey pins that the cmd // fast paths (root refusal, pre-launch WARN) see an operator-YAML-only // permissionMode: allow-all token, not only an explicit flag. -func TestADR_0365_AuthoritativePostureFoldsPermissionModeKey(t *testing.T) { +func TestADR_0375_AuthoritativePostureFoldsPermissionModeKey(t *testing.T) { path := filepath.Join(t.TempDir(), "operator.yaml") if err := os.WriteFile(path, []byte("permissionMode: yolo\n"), 0o600); err != nil { t.Fatal(err) diff --git a/internal/app/posture.go b/internal/app/posture.go index cc2504ad1e..e47ebb3a82 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -261,7 +261,7 @@ func foldOperatorPosture(cfg Config) Config { } cfg.Posture = parsePosture(yamlPosture) cfg.diag().Log(context.Background(), port.LevelWarn, - "posture: the settings.yaml posture: key is DEPRECATED; use permissionMode: instead (ADR 0365)", + "posture: the settings.yaml posture: key is DEPRECATED; use permissionMode: instead (ADR 0375)", "posture", yamlPosture) return cfg } @@ -275,7 +275,7 @@ func foldOperatorPosture(cfg Config) Config { // decision drive the real Build and read its structured diagnostic. func ResolveAuthoritativePosture(cfg Config) Posture { cfg.permResolver = buildPermResolver(cfg) - // Fold the permission-mode token first (ADR 0365), so an operator-YAML-only + // Fold the permission-mode token first (ADR 0375), so an operator-YAML-only // permissionMode: auto/yolo reaches the cmd fast paths. An invalid token is // Build's to report; the pre-check falls back to the deprecated surface. if folded, err := foldPermissionMode(cfg); err == nil { diff --git a/internal/configgen/build.go b/internal/configgen/build.go index 9c17f1bbc3..cdadad80af 100644 --- a/internal/configgen/build.go +++ b/internal/configgen/build.go @@ -403,7 +403,7 @@ func permissionModeSubtree(docs Docs) *Subtree { return &Subtree{ Key: "permissionMode", Tier: TierOperator, - Doc: "OPERATOR-TIER named permission mode (ADR 0365): plan, default, accept-edits, trusted, " + + Doc: "OPERATOR-TIER named permission mode (ADR 0375): plan, default, accept-edits, trusted, " + "trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, " + "fixed at startup, and the mode new sessions start in, which each session may change. auto " + "and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. " + @@ -425,7 +425,7 @@ func postureSubtree(docs Docs) *Subtree { return &Subtree{ Key: "posture", Tier: TierOperator, - Doc: "DEPRECATED: use permissionMode: instead (ADR 0365); still honoured with a WARN for one release. " + + Doc: "DEPRECATED: use permissionMode: instead (ADR 0375); still honoured with a WARN for one release. " + "OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated " + "trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project " + "cannot raise the automation posture). Empty = keep the CLI/default.", diff --git a/internal/configgen/configgen_test.go b/internal/configgen/configgen_test.go index 129c4e7036..182c9f5d68 100644 --- a/internal/configgen/configgen_test.go +++ b/internal/configgen/configgen_test.go @@ -110,7 +110,7 @@ func authoritativeKeys() []string { collect("mcp.servers.auth.oauth.tools", permconfig.MCPStaticToolProfile{}) // posture is a bare scalar Config field, not a *Section. keys = append(keys, "posture") - // permissionMode is likewise a bare scalar Config field (ADR 0365). + // permissionMode is likewise a bare scalar Config field (ADR 0375). keys = append(keys, "permissionMode") // output-economy is absent: the setting was REMOVED (a // clean break) and MUST NOT appear in generated artifacts (pinned by @@ -368,7 +368,7 @@ func TestSubtreeTiersAreAsPinned(t *testing.T) { "permissions": configgen.TierProject, // allow/ask/deny + subagent: project-settable (allows trust-gated) "guardrails": configgen.TierOperator, // operator-only: a project cannot weaken a security checker "posture": configgen.TierOperator, // operator-only: a project cannot raise the automation posture - "permissionMode": configgen.TierOperator, // operator-only: a project cannot choose its own permission mode (ADR 0365) + "permissionMode": configgen.TierOperator, // operator-only: a project cannot choose its own permission mode (ADR 0375) "reasoning-effort": configgen.TierOperator, // operator-only: a project cannot raise the model's reasoning spend "plan-mode-auto-approve": configgen.TierOperator, // operator-only: a project cannot grant an autonomous approval capability (issue #206) "providers": configgen.TierOperator, // operator-only: a project cannot choose LLM endpoints or auth posture diff --git a/internal/configgen/settings.skeleton.yaml b/internal/configgen/settings.skeleton.yaml index 00cb59f1ba..6c21047dec 100644 --- a/internal/configgen/settings.skeleton.yaml +++ b/internal/configgen/settings.skeleton.yaml @@ -97,7 +97,7 @@ # failClosed: false #| === permissionMode === (tier: operator) -#| OPERATOR-TIER named permission mode (ADR 0365): plan, default, accept-edits, trusted, +#| OPERATOR-TIER named permission mode (ADR 0375): plan, default, accept-edits, trusted, #| trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide #| posture, fixed at startup, and the mode new sessions start in, which each session may #| change. auto and yolo refuse to start without a guardrails checker unless guardrails @@ -107,7 +107,7 @@ # permissionMode: trusted-accept-edits #| === posture === (tier: operator) -#| DEPRECATED: use permissionMode: instead (ADR 0365); still honoured with a WARN for +#| DEPRECATED: use permissionMode: instead (ADR 0375); still honoured with a WARN for #| one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the #| graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a #| project cannot raise the automation posture). Empty = keep the CLI/default. diff --git a/user-docs/reference/configuration.md b/user-docs/reference/configuration.md index e2d2a4d80a..1f00f6ea28 100644 --- a/user-docs/reference/configuration.md +++ b/user-docs/reference/configuration.md @@ -78,17 +78,17 @@ OPERATOR-TIER LLM content-checker (issue #27). Parsed strictly. A project-tier g Tier: **operator** -OPERATOR-TIER named permission mode (ADR 0365): plan, default, accept-edits, trusted, trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, fixed at startup, and the mode new sessions start in, which each session may change. auto and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. +OPERATOR-TIER named permission mode (ADR 0375): plan, default, accept-edits, trusted, trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, fixed at startup, and the mode new sessions start in, which each session may change. auto and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. | Value | Type | Default | Description | | --- | --- | --- | --- | -| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0365: plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets the posture and the default session mode together and supersedes the deprecated posture: key. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | +| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0375: plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets the posture and the default session mode together and supersedes the deprecated posture: key. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | ## `posture` Tier: **operator** -DEPRECATED: use permissionMode: instead (ADR 0365); still honoured with a WARN for one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project cannot raise the automation posture). Empty = keep the CLI/default. +DEPRECATED: use permissionMode: instead (ADR 0375); still honoured with a WARN for one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project cannot raise the automation posture). Empty = keep the CLI/default. | Value | Type | Default | Description | | --- | --- | --- | --- | From 1de2c92ad2e0a4f67a431b5a6d1a62087adbf971 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Mon, 5 Oct 2026 16:14:42 +0300 Subject: [PATCH 11/48] test(permissions): declare the checker choice at the remaining allow-all build sites The ADR 0375 allow-all admission gate (checkerRefusal) refuses an auto or yolo build that has neither a guardrails checker nor the explicit --guardrails off kill-switch. The branch updated most allow-all composition tests, but the microVM and remote-execution tests still built with AllowAllTools or PostureAuto and no checker choice, so Build failed before the scenario ran (CI: Test, Test (race), Linux amd64 KVM). The kind job's deploy:check still required --posture in the oidc chart render after the chart switched to --permission-mode. It now requires --permission-mode and the --guardrails checker declaration the chart must emit for auto to start. Co-authored-by: Mecatl --- Taskfile.yml | 2 +- internal/adapter/microvm/production_e2e_test.go | 2 +- internal/app/microvm_harness_context_test.go | 6 +++--- internal/app/microvm_lifecycle_e2e_test.go | 4 ++-- internal/app/remote_execution_test.go | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 41eb3d59dc..d1c032ba32 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -864,7 +864,7 @@ tasks: set -eu -o pipefail missing="" rendered=$(helm template production deploy/helm/mecak8s --set '{{.SAFE_SET}}') - for arg in --grpc-addr --http-addr --redis-url --session-lease-k8s-namespace --headless --posture --oidc-issuer --oidc-audience --oidc-max-jwks-staleness=1h; do + for arg in --grpc-addr --http-addr --redis-url --session-lease-k8s-namespace --headless --permission-mode --guardrails --oidc-issuer --oidc-audience --oidc-max-jwks-staleness=1h; do echo "$rendered" | grep -q -- "$arg" || missing="$missing $arg" done if [ -n "$missing" ]; then diff --git a/internal/adapter/microvm/production_e2e_test.go b/internal/adapter/microvm/production_e2e_test.go index 0e3986c8e3..78fac1a2e8 100644 --- a/internal/adapter/microvm/production_e2e_test.go +++ b/internal/adapter/microvm/production_e2e_test.go @@ -189,7 +189,7 @@ func TestMicroVMDefaultPlacementDailyHarnessJourney(t *testing.T) { ) built, err := app.Build(ctx, app.Config{ Workspace: source, StoreDir: filepath.Join(root, "store"), MockProvider: provider, - Shell: "/bin/sh", AllowAllTools: true, NoSoul: true, LearningMode: learning.Off, + Shell: "/bin/sh", AllowAllTools: true, GuardrailsDisabled: true, NoSoul: true, LearningMode: learning.Off, MemoryDir: filepath.Join(root, "memory"), UserModelDir: filepath.Join(root, "user-model"), PlacementProvider: placement, PlacementScope: scope, EnvironmentForkers: map[session.EnvironmentKind]tool.EnvironmentForker{"microvm": placement}, diff --git a/internal/app/microvm_harness_context_test.go b/internal/app/microvm_harness_context_test.go index 9e3b5c3cd4..160dd03ce9 100644 --- a/internal/app/microvm_harness_context_test.go +++ b/internal/app/microvm_harness_context_test.go @@ -430,7 +430,7 @@ func TestMicroVMSuccessorRetainsPlacementAndContext(t *testing.T) { if !selected { cfg.PermissionConfigs = nil } - cfg.Shell, cfg.AllowAllTools = "/bin/sh", true + cfg.Shell, cfg.AllowAllTools, cfg.GuardrailsDisabled = "/bin/sh", true, true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.NewToolCall("still-attached", "Shell", json.RawMessage(`{"command":"test -f AGENTS.md"}`))), mockllm.TextTurn("successor")) @@ -568,7 +568,7 @@ func TestMicroVMRepositorySelectionDoesNotGrantProjectAdmission(t *testing.T) { daemon := startPlacementTestDaemon(t) cfg := microVMHarnessConfig(t, daemon, "repository") cfg.TrustProject = false - cfg.Posture, cfg.PostureFlagSet = PostureAuto, true + cfg.Posture, cfg.PostureFlagSet, cfg.GuardrailsDisabled = PostureAuto, true, true built, err := buildIsolated(t, t.Context(), cfg) if err != nil { t.Fatal(err) @@ -601,7 +601,7 @@ func TestMicroVMRequiredRepositorySourceFailsForNoFS(t *testing.T) { func TestMicroVMSelectedContextFreshnessAndReadEvidence(t *testing.T) { daemon := startPlacementTestDaemon(t) cfg := microVMHarnessConfig(t, daemon, "repository") - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true diag := newCapturingDiagnostics() cfg.Diagnostics = diag var requests []port.LLMRequest diff --git a/internal/app/microvm_lifecycle_e2e_test.go b/internal/app/microvm_lifecycle_e2e_test.go index 4c4feca14f..d61b497c3c 100644 --- a/internal/app/microvm_lifecycle_e2e_test.go +++ b/internal/app/microvm_lifecycle_e2e_test.go @@ -638,7 +638,7 @@ func TestMicroVMOperatorJourneyIsLazyIsolatedAndRestartExact(t *testing.T) { config := func(provider *mockllm.Provider) Config { configured, err := ConfigureExecution(Config{ Workspace: hostSource, StoreDir: storeDir, UseMock: true, MockProvider: provider, - Shell: "/bin/sh", AllowAllTools: true, TrustProject: true, PermissionConfigs: []string{settings}, + Shell: "/bin/sh", AllowAllTools: true, GuardrailsDisabled: true, TrustProject: true, PermissionConfigs: []string{settings}, MicroVMReadyRequest: func(microvmmanager.GuestEgressSelection) (microvmmanager.ReadyRequest, error) { return microvmmanager.ReadyRequest{}, nil }, @@ -815,7 +815,7 @@ func TestMicroVMScheduledPlacementSurvivesFiresRestartAndDeletion(t *testing.T) } built, err := Build(ctx, Config{ Workspace: workspace, StoreDir: storeDir, UseMock: true, MockProvider: llm, - Shell: "/bin/sh", AllowAllTools: true, TrustProject: true, + Shell: "/bin/sh", AllowAllTools: true, GuardrailsDisabled: true, TrustProject: true, PlacementProvider: provider, PlacementScope: scope, EnvironmentForkers: map[session.EnvironmentKind]tool.EnvironmentForker{session.EnvironmentKind("microvm"): provider}, EnvironmentMergers: map[session.EnvironmentKind]tool.EnvironmentMerger{session.EnvironmentKind("microvm"): provider}, diff --git a/internal/app/remote_execution_test.go b/internal/app/remote_execution_test.go index 1de880874e..4c0022dbcd 100644 --- a/internal/app/remote_execution_test.go +++ b/internal/app/remote_execution_test.go @@ -236,7 +236,7 @@ func TestRemoteExecutionPreservesOperatorPermissionsUnderAuto(t *testing.T) { session.NewToolCall("allowed", "Shell", json.RawMessage(`{"command":"echo allowed"}`)), session.NewToolCall("project-ask", "Shell", json.RawMessage(`{"command":"echo project-ask"}`)), ), mockllm.TextTurn("done")) - cfg := Config{MockProvider: llm, Workspace: project, Posture: PostureAuto, PermissionsConventional: true, NoSoul: true, RemoteExecution: true, PlacementScope: "remote", PlacementProvider: remoteFactoryPlacement{env: env}} + cfg := Config{MockProvider: llm, Workspace: project, Posture: PostureAuto, GuardrailsDisabled: true, PermissionsConventional: true, NoSoul: true, RemoteExecution: true, PlacementScope: "remote", PlacementProvider: remoteFactoryPlacement{env: env}} if source == "explicit" { cfg.PermissionConfigs = []string{operatorPath} } @@ -357,7 +357,7 @@ func TestRemoteExecutionRealFactoryCarriesPostureAndAttenuatedCatalog(t *testing if err := os.WriteFile(filepath.Join(commandDir, "project-only.md"), []byte("LOCAL_COMMAND_MARKER_DO_NOT_LOAD"), 0o600); err != nil { t.Fatal(err) } - built, err := buildIsolated(t, context.Background(), Config{MockProvider: provider, PlacementProvider: remoteFactoryPlacement{env: env}, PlacementScope: "remote", RemoteExecution: true, Workspace: localProject, TrustProject: true, AllowAllTools: true, EnableCommands: true, SkillsConventional: true, NoSoul: true, SchedulerEnabled: false}) + built, err := buildIsolated(t, context.Background(), Config{MockProvider: provider, PlacementProvider: remoteFactoryPlacement{env: env}, PlacementScope: "remote", RemoteExecution: true, Workspace: localProject, TrustProject: true, AllowAllTools: true, GuardrailsDisabled: true, EnableCommands: true, SkillsConventional: true, NoSoul: true, SchedulerEnabled: false}) if err != nil { t.Fatal(err) } From 7bc4a8d1532325030943324f33ec60a543e6aea3 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Thu, 8 Oct 2026 14:07:13 +0300 Subject: [PATCH 12/48] test(permissions): declare the checker choice at allow-all sites added on main Tests that main added since the branch point build with AllowAllTools but no guardrails decision, which the permission-mode contract now refuses. Declare --guardrails off at those sites, re-enable the checker where a test configures one, and restore main's non-allow-all MCP reconciliation scenario that expects a permission ask. Regenerate the server CLI reference. Co-authored-by: Mecatl --- .../harness_context_execution_source_test.go | 2 +- .../app/harness_context_generation_test.go | 4 +- .../harness_context_replace_lifetime_test.go | 2 +- internal/app/hierarchy_fork_repair_test.go | 4 +- internal/app/hierarchy_test.go | 18 +++--- internal/app/mcp_refresh_acceptance_test.go | 4 +- ...rver_provider_recovery_composition_test.go | 2 +- ...server_provider_recovery_deadlines_test.go | 2 + user-docs/reference/server-cli.md | 63 ++++++++++++++----- 9 files changed, 65 insertions(+), 36 deletions(-) diff --git a/internal/app/harness_context_execution_source_test.go b/internal/app/harness_context_execution_source_test.go index 390868752d..6b7ffa0a12 100644 --- a/internal/app/harness_context_execution_source_test.go +++ b/internal/app/harness_context_execution_source_test.go @@ -169,7 +169,7 @@ func TestRepositoryForkCarriesSnapshotsAcrossNewWorkspaceBindings(t *testing.T) var requests []port.LLMRequest cfg := harnessExecutionConfig(t, provider, &requests) cfg.Workspace = root - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true cfg.HarnessInstructionSources = nil cfg.HarnessCommandSources = nil registerRepositorySources(&cfg) diff --git a/internal/app/harness_context_generation_test.go b/internal/app/harness_context_generation_test.go index 1fc36492ba..e67eefa3ef 100644 --- a/internal/app/harness_context_generation_test.go +++ b/internal/app/harness_context_generation_test.go @@ -502,7 +502,7 @@ func TestChildHierarchyProviderFactoryScopesPreserveForkSnapshotsAndIsolation(t t.Fatal(err) } cfg := hcConfiguredFiles(t, source) - cfg.Workspace, cfg.Shell, cfg.AllowAllTools, cfg.NoSoul = website, "/bin/sh", true, true + cfg.Workspace, cfg.Shell, cfg.AllowAllTools, cfg.NoSoul, cfg.GuardrailsDisabled = website, "/bin/sh", true, true, true var requests []port.LLMRequest args := `{"prompt":"read nested file","model":"mock"}` if fork { @@ -573,7 +573,7 @@ func TestChildNoFSForkRetainsRootWithoutDiscoveringNested(t *testing.T) { } } cfg := hcConfiguredFiles(t, source) - cfg.AllowAllTools, cfg.NoSoul = true, true + cfg.AllowAllTools, cfg.NoSoul, cfg.GuardrailsDisabled = true, true, true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) diff --git a/internal/app/harness_context_replace_lifetime_test.go b/internal/app/harness_context_replace_lifetime_test.go index 7086974fa1..9df4d80927 100644 --- a/internal/app/harness_context_replace_lifetime_test.go +++ b/internal/app/harness_context_replace_lifetime_test.go @@ -46,7 +46,7 @@ func TestBuildReplacePolicyGlobalStableAcrossReadDiscovery(t *testing.T) { kinds := harnessEmptyKinds() kinds.Instructions = permconfig.HarnessContextKind{Sources: []string{"project", "global"}, Mode: "replace"} cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: []string{"project", "global"}, Kinds: kinds}) - cfg.Workspace, cfg.AllowAllTools = root, true + cfg.Workspace, cfg.AllowAllTools, cfg.GuardrailsDisabled = root, true, true global := &changingPolicyGlobal{} cfg.HarnessInstructionSources = []HarnessSourceRegistration[prompt.InstructionAssembler]{ {ID: "project", Provenance: HarnessProvenancePolicy{Fixed: harnessProjectTier}, Bind: func(context.Context, HarnessSourceScope) (prompt.InstructionAssembler, func() error, error) { diff --git a/internal/app/hierarchy_fork_repair_test.go b/internal/app/hierarchy_fork_repair_test.go index 9e13ef4078..8500e21e6d 100644 --- a/internal/app/hierarchy_fork_repair_test.go +++ b/internal/app/hierarchy_fork_repair_test.go @@ -24,7 +24,7 @@ func TestBuildSamePlacementForkKeepsExaminedInstructions(t *testing.T) { } cfg := hcConfiguredFiles(t, ws) cfg.Workspace = ws.Root() - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.ToolCall{ID: "read", Name: "Read", Args: json.RawMessage(`{"path":"nested/draft.txt"}`)}), mockllm.TextTurn("parent"), mockllm.TextTurn("fork"), mockllm.TextTurn("fresh")) @@ -142,7 +142,7 @@ func TestBuildForkDiscardsRemovedBinding(t *testing.T) { } cfg := hcConfiguredFiles(t, old) cfg.Workspace = execution.Root() - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true cfg.HarnessInstructionSources[0].Scope = HarnessSourceScopePrincipal binds := 0 cfg.HarnessInstructionSources[0].Bind = func(context.Context, HarnessSourceScope) (prompt.InstructionAssembler, func() error, error) { diff --git a/internal/app/hierarchy_test.go b/internal/app/hierarchy_test.go index 931cfd18ac..3ac7256a1d 100644 --- a/internal/app/hierarchy_test.go +++ b/internal/app/hierarchy_test.go @@ -146,7 +146,7 @@ func TestHierarchyFactorySelectedSeparateSource(t *testing.T) { if err := os.WriteFile(filepath.Join(cfg.Workspace, "nested/draft.txt"), []byte("draft"), 0600); err != nil { t.Fatal(err) } - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.ToolCall{ID: "read", Name: "Read", Args: json.RawMessage(`{"path":"nested/draft.txt"}`)}), mockllm.TextTurn("done")) @@ -193,7 +193,7 @@ func TestHierarchyFactoryAbsentRootLoadsNestedThroughHostWrapper(t *testing.T) { if err := os.WriteFile(filepath.Join(cfg.Workspace, "nested/draft.txt"), []byte("draft"), 0600); err != nil { t.Fatal(err) } - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.ToolCall{ID: "read", Name: "Read", Args: json.RawMessage(`{"path":"nested/draft.txt"}`)}), mockllm.TextTurn("done")) @@ -245,7 +245,7 @@ func TestHierarchyFactoryMixedHostSourceCachesEmptyGlobal(t *testing.T) { if err := os.WriteFile(filepath.Join(cfg.Workspace, "nested/draft.txt"), []byte("draft"), 0600); err != nil { t.Fatal(err) } - cfg.AllowAllTools = true + cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) @@ -279,7 +279,7 @@ func TestDefaultSourceChildAndConversationForkInstructionSnapshots(t *testing.T) if err := os.WriteFile(filepath.Join(ws.Root(), "nested/draft.txt"), []byte("draft"), 0600); err != nil { t.Fatal(err) } - cfg := Config{Workspace: ws.Root(), UseMock: true, TrustProject: true, Headless: true, NoSoul: true, NoShell: true, AllowAllTools: true, UserModelDir: t.TempDir()} + cfg := Config{Workspace: ws.Root(), UseMock: true, TrustProject: true, Headless: true, NoSoul: true, NoShell: true, AllowAllTools: true, GuardrailsDisabled: true, UserModelDir: t.TempDir()} var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) @@ -317,14 +317,14 @@ func TestHierarchyNoFSChildKeepsOnlyStartingGuidance(t *testing.T) { for _, configured := range []bool{false, true} { t.Run(fmt.Sprintf("configured=%v", configured), func(t *testing.T) { ws := osfsWorkspaceForHierarchy(t) - cfg := Config{Workspace: ws.Root(), UseMock: true, TrustProject: true, Headless: true, NoSoul: true, NoShell: true, AllowAllTools: true, UserModelDir: t.TempDir()} + cfg := Config{Workspace: ws.Root(), UseMock: true, TrustProject: true, Headless: true, NoSoul: true, NoShell: true, AllowAllTools: true, GuardrailsDisabled: true, UserModelDir: t.TempDir()} prefix := "." if configured { // The execution root is below the source root. Both ancestors are // starting guidance, although only one has source-relative path '.'. prefix = "website" cfg = hcConfiguredFiles(t, ws) - cfg.NoSoul, cfg.NoShell, cfg.AllowAllTools = true, true, true + cfg.NoSoul, cfg.NoShell, cfg.AllowAllTools, cfg.GuardrailsDisabled = true, true, true, true cfg.HarnessInstructionSources[0].Bind = func(context.Context, HarnessSourceScope) (prompt.InstructionAssembler, func() error, error) { return prompt.RootAssembler{Source: ws, SourceID: "source", SourcePrefix: prefix}, nil, nil } @@ -407,7 +407,7 @@ func TestHierarchyDefaultSourceChildPlacementMapping(t *testing.T) { if err := execution.Write(t.Context(), "nested/draft.txt", []byte("execution draft")); err != nil { t.Fatal(err) } - cfg := Config{Workspace: selected.Root(), UseMock: true, TrustProject: true, Headless: true, NoSoul: true, Shell: "/bin/sh", AllowAllTools: true, UserModelDir: t.TempDir()} + cfg := Config{Workspace: selected.Root(), UseMock: true, TrustProject: true, Headless: true, NoSoul: true, Shell: "/bin/sh", AllowAllTools: true, GuardrailsDisabled: true, UserModelDir: t.TempDir()} var requests []port.LLMRequest cfg.MockProvider = mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(r port.LLMRequest) { requests = append(requests, r) })}, mockllm.ToolCallTurn(session.ToolCall{ID: "parent-read", Name: "Read", Args: json.RawMessage(`{"path":"nested/draft.txt"}`)}), @@ -552,7 +552,7 @@ func TestHierarchyConfiguredNilRefreshRetainsGuidance(t *testing.T) { kinds := harnessEmptyKinds() kinds.Instructions = permconfig.HarnessContextKind{Sources: []string{"custom", "lower"}, Mode: mode} cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: []string{"custom", "lower"}, Kinds: kinds}) - cfg.AllowAllTools, cfg.NoSoul, cfg.NoShell = true, true, true + cfg.AllowAllTools, cfg.NoSoul, cfg.NoShell, cfg.GuardrailsDisabled = true, true, true, true source := &failingRefreshInstructions{} lower := &policyCountWorkspace{Workspace: memfs.NewWorkspace("/lower")} harnessSeed(t, lower.Workspace, "AGENTS.md", "LOWER-GUIDANCE") @@ -662,7 +662,7 @@ func TestHierarchyConfiguredFactoryPartialRefresh(t *testing.T) { kinds := harnessEmptyKinds() kinds.Instructions = permconfig.HarnessContextKind{Sources: ids, Mode: mode} cfg := harnessPolicyConfig(t, permconfig.HarnessContextSection{EnabledSources: ids, Kinds: kinds}) - cfg.AllowAllTools, cfg.NoSoul, cfg.NoShell = true, true, true + cfg.AllowAllTools, cfg.NoSoul, cfg.NoShell, cfg.GuardrailsDisabled = true, true, true, true cfg.HarnessInstructionSources = []HarnessSourceRegistration[prompt.InstructionAssembler]{ {ID: "fault", Provenance: HarnessProvenancePolicy{Fixed: "project"}, Bind: func(context.Context, HarnessSourceScope) (prompt.InstructionAssembler, func() error, error) { return prompt.NewMultiAssembler(prompt.RootAssembler{Source: fault, SourceID: "fault", SourcePrefix: "."}, hcAssembler("FAULT-GLOBAL")), nil, nil diff --git a/internal/app/mcp_refresh_acceptance_test.go b/internal/app/mcp_refresh_acceptance_test.go index 3d08246039..4e50be3dfd 100644 --- a/internal/app/mcp_refresh_acceptance_test.go +++ b/internal/app/mcp_refresh_acceptance_test.go @@ -62,9 +62,7 @@ func TestMCPSourceReconciliation_Scenario4_RealBuildPublicationAndExplicitGrant( defer flaky.Close() built, err := buildIsolated(t, ctx, Config{ Workspace: workspace, StoreDir: storeDir, MockProvider: provider, NoSoul: true, - AllowAllTools: true, - GuardrailsDisabled: true, - MCPServers: []mcp.ServerConfig{{Name: "live", URL: newMCPTestServer(t)}, {Name: "flaky", URL: flaky.URL}}, + MCPServers: []mcp.ServerConfig{{Name: "live", URL: newMCPTestServer(t)}, {Name: "flaky", URL: flaky.URL}}, }) if err != nil { t.Fatalf("Build with published MCP runtime: %v", err) diff --git a/internal/app/server_provider_recovery_composition_test.go b/internal/app/server_provider_recovery_composition_test.go index 73280e5b38..141826b8a4 100644 --- a/internal/app/server_provider_recovery_composition_test.go +++ b/internal/app/server_provider_recovery_composition_test.go @@ -25,7 +25,7 @@ func recoveryAppConfig(t *testing.T, endpoint string) Config { t.Helper() return isolateConfig(t, Config{ Workspace: t.TempDir(), StoreDir: t.TempDir(), NoSoul: true, NoUserModel: true, - Model: "gpt-5", UseOpenAI: true, OpenAIKey: "test", AllowAllTools: true, + Model: "gpt-5", UseOpenAI: true, OpenAIKey: "test", AllowAllTools: true, GuardrailsDisabled: true, ContextWindowOverride: defaultContextWindowTokens, ProviderOverrides: permconfig.ProviderOverrides{providerOpenAI: {BaseURL: endpoint + "/v1"}}, envDetector: fakeEnv(nil), liveModelHTTPClient: offlineHTTPClient(), diff --git a/internal/app/server_provider_recovery_deadlines_test.go b/internal/app/server_provider_recovery_deadlines_test.go index b62ccbacd7..61586191fc 100644 --- a/internal/app/server_provider_recovery_deadlines_test.go +++ b/internal/app/server_provider_recovery_deadlines_test.go @@ -131,6 +131,7 @@ func TestServerProviderRecovery_Scenario4_ShorterAuxiliaryAndScheduleDeadlines(t defer func() { cancel(); srv.Close() }() cfg := recoveryAppConfig(t, srv.URL) cfg.LLMBreakerCooldown = 10 * time.Millisecond + cfg.GuardrailsDisabled = false // recoveryAppConfig declares off; this test configures a checker instead cfg.GuardrailsModel = cfg.Model cfg.GuardrailsOnCheckerDown = policy cfg.GuardrailsRules = []GuardrailRule{{Match: "Write", Phases: []string{"pre"}, Mode: "block"}} @@ -230,6 +231,7 @@ func TestServerProviderRecovery_Scenario4_CheckerDownPolicyAtToolDispatch(t *tes })) defer srv.Close() cfg := recoveryAppConfig(t, srv.URL) + cfg.GuardrailsDisabled = false // recoveryAppConfig declares off; this test configures a checker instead cfg.GuardrailsModel = cfg.Model cfg.GuardrailsOnCheckerDown = policy cfg.GuardrailsRules = []GuardrailRule{{Match: "Grep", Phases: []string{"pre"}, Mode: "block"}} diff --git a/user-docs/reference/server-cli.md b/user-docs/reference/server-cli.md index 2f0b8dfd36..4cfde8722d 100644 --- a/user-docs/reference/server-cli.md +++ b/user-docs/reference/server-cli.md @@ -364,6 +364,16 @@ Flags: --permission-config value path to a repeatable YAML permission configuration. CLI rules have highest precedence; configured deny and ask rules always override allows. + --permission-mode string + permission mode, one of: plan, default, accept-edits, trusted, trusted-accept- + edits, auto, yolo. Sets two things: the process-wide posture, fixed at startup + (strict for plan, default, and accept-edits; trusted for trusted and trusted- + accept-edits; auto; yolo), and the session mode new sessions start in, which + each session may change. Default: default. auto and yolo allow tools without + asking, so they need a guardrails checker (--guardrails-model) or an explicit - + -guardrails off, and are refused for root unless MECATL_SANDBOX=1 or + IS_SANDBOX=1. Deny rules and configured ask rules still apply. Replaces the + deprecated --posture and --yolo; --trust-project still combines with it. --permissions-conventional load project and user permission settings for each session. Enabled by default. Project allow rules require --trust-project; project deny and ask rules always @@ -372,11 +382,12 @@ Flags: approve plan-mode results automatically in headless mode. Interactive sessions and non-plan requests are unaffected. Disabled by default. --posture string - permission posture: strict prompts mutations; trusted applies project allow - rules; auto allows tools and relaxes main shell substitutions; yolo also runs - child command substitutions. Deny rules and configured ask rules still apply. - strict is the default. --trust-project and --yolo select trusted and yolo. auto - and yolo are refused for root outside MECATL_SANDBOX. + DEPRECATED: use --permission-mode. Permission posture: strict prompts + mutations; trusted applies project allow rules; auto allows tools and relaxes + main shell substitutions; yolo also runs child command substitutions. Deny + rules and configured ask rules still apply. strict is the default. --trust- + project and --yolo select trusted and yolo. auto and yolo are refused for root + outside MECATL_SANDBOX. --product-metrics send anonymous product-adoption metrics to Stacklok: version, OS and architecture, enabled features, and coarse session, run, and tool-call counts. @@ -482,7 +493,9 @@ Flags: --subagent-ask-reviewer string model identifier or --model-alias for reviewing child permission requests in headless mode. An allow applies only to that request; denied or failed reviews - deny it. Empty disables reviews. + deny it. Empty leaves reviews off, except that a headless auto or yolo + permission mode turns them on by default (ask-reviewer model slot, else the + session model); off disables reviews explicitly. --subagent-ask-reviewer-max-denies int maximum consecutive denied, failed, or timed-out child-permission reviews before later requests are automatically denied. An allowed review resets the @@ -554,10 +567,11 @@ Flags: default session workspace root (default "") --yolo - alias for --posture=yolo. Allows tools server-wide and lets child command - substitutions run automatically. Deny rules and configured ask rules still - apply. Intended only for isolated, ephemeral, single-tenant environments. - Refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1. + DEPRECATED: use --permission-mode yolo. Alias for --posture=yolo. Allows tools + server-wide and lets child command substitutions run automatically. Deny rules + and configured ask rules still apply. Intended only for isolated, ephemeral, + single-tenant environments. Refused for root unless MECATL_SANDBOX=1 or + IS_SANDBOX=1. ``` ## mecak8s @@ -804,14 +818,26 @@ Usage: mecak8s [flags] 5s) --permission-config value Trusted permission YAML file. Repeatable + --permission-mode string + Permission mode, one of: plan, default, accept-edits, trusted, trusted-accept- + edits, auto, yolo. Sets two things: the process-wide posture, fixed at startup + (strict for plan, default, and accept-edits; trusted for trusted and trusted- + accept-edits; auto; yolo), and the session mode new sessions start in, which + each session may change. Default: auto (posture auto, default session mode). + auto and yolo allow tools without asking, so they need a guardrails checker (-- + guardrails-model or the guardrail model slot) or an explicit --guardrails off, + and require MECATL_SANDBOX when running as root. Deny rules and configured ask + rules still apply. Replaces the deprecated --posture; --trust-project still + combines with it --permissions-conventional Discover project and user permission settings for each session (default true) --posture string - Permission posture: strict prompts for mutations; trusted honors project allow - rules; auto allows tools by default and relaxes main shell substitutions while - child injection defenses remain enabled; yolo also runs child command - substitutions automatically. Deny rules and configured ask rules still apply. - auto and yolo require MECATL_SANDBOX when running as root (default "auto") + DEPRECATED: use --permission-mode. Permission posture: strict prompts for + mutations; trusted honors project allow rules; auto allows tools by default and + relaxes main shell substitutions while child injection defenses remain enabled; + yolo also runs child command substitutions automatically. Deny rules and + configured ask rules still apply. auto and yolo require MECATL_SANDBOX when + running as root (default "auto") --product-metrics Report anonymous product-adoption metrics to Stacklok. Reports version, OS/architecture, enabled features, and aggregate counts, never prompts, file @@ -888,7 +914,9 @@ Usage: mecak8s [flags] Path to a user persona file. Empty uses the conventional location --subagent-ask-reviewer string Model ID or alias for reviewing child permission requests in headless mode. - Empty disables the reviewer + Empty leaves the reviewer off, except that the auto and yolo permission modes + turn it on by default (ask-reviewer model slot, else the session model); off + disables it explicitly --subagent-ask-reviewer-max-denies int Consecutive non-allow outcomes that disable the reviewer for the run. Values less than or equal to zero use the default (default 3) @@ -923,7 +951,8 @@ Usage: mecak8s [flags] override is always proxy mode (default "auto") --trust-project Honor a discovered project's allow rules. Deny and ask rules are always - honored; equivalent to --posture=trusted + honored; raises the posture to at least trusted and combines with --permission- + mode --user-model-dir string Directory for the user model. Empty uses the conventional location --workspace string From 81adf0158b2d38fa807991b150e892c89848d34f Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Thu, 8 Oct 2026 14:24:12 +0300 Subject: [PATCH 13/48] refactor(mecatequi): extract explicit-flag recording from parseFlags The permission-mode flag pushed parseFlags past the gocyclo limit after rebasing onto main. Move the fs.Visit bookkeeping into its own function. Co-authored-by: Mecatl --- cmd/mecatequi/flags.go | 63 +++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/cmd/mecatequi/flags.go b/cmd/mecatequi/flags.go index abaf6f582a..813c9de804 100644 --- a/cmd/mecatequi/flags.go +++ b/cmd/mecatequi/flags.go @@ -205,35 +205,7 @@ func parseFlags(argv []string) (flags, error) { return flags{}, err } - // Record whether --posture was set EXPLICITLY (vs the empty default) so - // composition lets CLI out-rank the operator-global settings.yaml posture: key. - fs.Visit(func(fl *flag.Flag) { - switch fl.Name { - case "posture": - f.postureFlagSet = true - case "permission-mode": - f.permissionModeFlagSet = true - case "shell": - f.shellFlagSet = true - case "subagent-model-router": - // Tri-state kill-switch: record that the flag was given so - // appConfig can distinguish unset / =false (kill-switch) / =true (inert). - f.subagentModelRouterSet = true - case "out-summary": - // Stdout-compact summary mode (issue #341): ONLY an EXPLICIT - // --out-summary=- selects it. The unset default also resolves to "-" - // but keeps the indented JSON — default behavior unchanged. - f.summaryCompact = f.outSummary == "-" - case "product-metrics": - f.productMetricsSet = true - } - if fl.Name == "reasoning-effort" { - f.reasoningEffortFlagSet = true - } - if fl.Name == "default-provider" { - f.defaultProviderFlagSet = true - } - }) + recordExplicitFlags(fs, &f) if err := validatePermissionModeFlags(f); err != nil { return flags{}, err } @@ -290,6 +262,39 @@ func parseFlags(argv []string) (flags, error) { return f, nil } +// recordExplicitFlags records which flags were set EXPLICITLY (vs their +// defaults), e.g. so composition lets CLI out-rank the operator-global +// settings.yaml posture: and permissionMode: keys. +func recordExplicitFlags(fs *flag.FlagSet, f *flags) { + fs.Visit(func(fl *flag.Flag) { + switch fl.Name { + case "posture": + f.postureFlagSet = true + case "permission-mode": + f.permissionModeFlagSet = true + case "shell": + f.shellFlagSet = true + case "subagent-model-router": + // Tri-state kill-switch: record that the flag was given so + // appConfig can distinguish unset / =false (kill-switch) / =true (inert). + f.subagentModelRouterSet = true + case "out-summary": + // Stdout-compact summary mode (issue #341): ONLY an EXPLICIT + // --out-summary=- selects it. The unset default also resolves to "-" + // but keeps the indented JSON — default behavior unchanged. + f.summaryCompact = f.outSummary == "-" + case "product-metrics": + f.productMetricsSet = true + } + if fl.Name == "reasoning-effort" { + f.reasoningEffortFlagSet = true + } + if fl.Name == "default-provider" { + f.defaultProviderFlagSet = true + } + }) +} + // configureFlags registers mecatequi's flags on fs. Keeping registration separate // lets help-output tests exercise the same flag descriptions that users see. func configureFlags(fs *flag.FlagSet, f *flags) { From 5bd4995c8f7eecedb1d09ac33f2e40e440f01f15 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Thu, 8 Oct 2026 15:08:43 +0300 Subject: [PATCH 14/48] chore(permissions): drop references to the deleted ADR 0375 Main removed docs/adr/, so the branch's ADR 0375 citations and its acceptance-criterion and decision numbers point at nothing. Remove them from comments, runtime messages, and the generated configuration reference, rename the TestADR_0375_* tests, and rename the mecatui vocabulary test file. Co-authored-by: Mecatl --- .github/actions/mecatequi/action.yml | 2 +- cmd/mecak8s/flags.go | 4 +- cmd/mecak8s/main_test.go | 4 +- cmd/mecak8s/permission_mode.go | 4 +- cmd/mecak8s/permission_mode_test.go | 10 ++-- cmd/mecak8s/telemetry_test.go | 4 +- cmd/mecated/main.go | 4 +- cmd/mecated/permission_mode.go | 6 +-- cmd/mecated/permission_mode_test.go | 12 ++--- cmd/mecatequi/flags.go | 4 +- cmd/mecatequi/permission_mode.go | 4 +- cmd/mecatequi/permission_mode_test.go | 8 +-- cmd/mecatui/client/client.go | 2 +- cmd/mecatui/config.go | 2 +- cmd/mecatui/main.go | 2 +- cmd/mecatui/permission_mode.go | 2 +- cmd/mecatui/permission_mode_test.go | 26 +++++----- cmd/mecatui/ui/help.go | 6 +-- cmd/mecatui/ui/model.go | 2 +- ....go => permission_mode_vocabulary_test.go} | 43 ++++++++-------- cmd/mecatui/ui/posture_badge_test.go | 2 +- cmd/mecatui/ui/view.go | 4 +- deploy/helm/mecak8s/chart_test.go | 4 +- internal/adapter/permconfig/resolve.go | 7 ++- internal/adapter/permconfig/schema.go | 4 +- internal/adapter/server/default_mode_test.go | 2 +- internal/adapter/server/mapper.go | 4 +- internal/app/build.go | 12 ++--- internal/app/permission_mode.go | 18 +++---- internal/app/permission_mode_test.go | 50 +++++++++---------- internal/app/posture.go | 4 +- internal/configgen/build.go | 4 +- internal/configgen/configgen_test.go | 4 +- internal/configgen/settings.skeleton.yaml | 10 ++-- user-docs/reference/configuration.md | 6 +-- 35 files changed, 143 insertions(+), 143 deletions(-) rename cmd/mecatui/ui/{permission_mode_adr0375_test.go => permission_mode_vocabulary_test.go} (84%) diff --git a/.github/actions/mecatequi/action.yml b/.github/actions/mecatequi/action.yml index 84bd7b805c..5c1ebb67bf 100644 --- a/.github/actions/mecatequi/action.yml +++ b/.github/actions/mecatequi/action.yml @@ -126,7 +126,7 @@ inputs: default: ${{ github.workspace }} permission-mode: description: >- - Permission mode (ADR 0375) → --permission-mode: one of plan, default, accept-edits, + Permission mode → --permission-mode: one of plan, default, accept-edits, trusted, trusted-accept-edits, auto, yolo. Empty (the input default) resolves to "auto", the documented CI mode (allow-all, child injection-defence ON), unless the deprecated `posture` input is set. "default" would CANCEL the run on the first diff --git a/cmd/mecak8s/flags.go b/cmd/mecak8s/flags.go index e77ffcfdac..574ecd1503 100644 --- a/cmd/mecak8s/flags.go +++ b/cmd/mecak8s/flags.go @@ -240,7 +240,7 @@ type config struct { // lets CLI out-rank the operator-global settings.yaml posture: key. posture string postureFlagSet bool - // permissionMode is the raw --permission-mode token (ADR 0375), validated at + // permissionMode is the raw --permission-mode token, validated at // parse time. Empty (the default) leaves the deprecated --posture default // "auto" in force, so an unconfigured pod keeps posture auto with the default // session mode and operator YAML can still override it. @@ -827,7 +827,7 @@ func appConfig(cfg config, diag port.Diagnostics, obs observability) app.Config PermissionConfigs: cfg.permissionConfigs, Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - // Permission mode (ADR 0375): an explicit token out-ranks the deprecated + // Permission mode: an explicit token out-ranks the deprecated // --posture (default auto) in app.Build's foldPermissionMode. PermissionMode: cfg.permissionMode, PermissionModeFlagSet: cfg.permissionModeFlagSet, diff --git a/cmd/mecak8s/main_test.go b/cmd/mecak8s/main_test.go index ce8e0de829..f467fc8577 100644 --- a/cmd/mecak8s/main_test.go +++ b/cmd/mecak8s/main_test.go @@ -453,7 +453,7 @@ func TestBuildOverRedisDrivesRunToCompletion(t *testing.T) { RedisAllowPlaintext: true, Interactive: false, // mecak8s headless default (Interactive=!headless) Posture: app.PostureAuto, - GuardrailsDisabled: true, // allow-all declares its checker choice (ADR 0375) + GuardrailsDisabled: true, // allow-all declares its checker choice PermissionsConventional: false, AgentsConventional: false, Diagnostics: port.NopDiagnostics{}, @@ -627,7 +627,7 @@ func TestDrainHTTPRouting(t *testing.T) { func TestServeWiresSeparateDrainListener(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", - "--guardrails=off", // the auto default must declare its checker choice (ADR 0375) + "--guardrails=off", // the auto default must declare its checker choice "--grpc-addr", freeLoopbackPort(t), "--http-addr", freeLoopbackPort(t), "--drain-addr", freeLoopbackPort(t), diff --git a/cmd/mecak8s/permission_mode.go b/cmd/mecak8s/permission_mode.go index 5882a8c446..c3b79a05ad 100644 --- a/cmd/mecak8s/permission_mode.go +++ b/cmd/mecak8s/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permissionModeHelp is the --permission-mode usage line (ADR 0375). It names +// permissionModeHelp is the --permission-mode usage line. It names // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + @@ -46,6 +46,6 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { replacement = tok.Name } diag.Log(context.Background(), port.LevelWarn, - "--posture is DEPRECATED; use --permission-mode instead (ADR 0375)", + "--posture is DEPRECATED; use --permission-mode instead", "posture", cfg.posture, "replacement", "--permission-mode "+replacement) } diff --git a/cmd/mecak8s/permission_mode_test.go b/cmd/mecak8s/permission_mode_test.go index 547663f69a..f610d3a18e 100644 --- a/cmd/mecak8s/permission_mode_test.go +++ b/cmd/mecak8s/permission_mode_test.go @@ -54,7 +54,7 @@ func k8sDeprecationWarnings(t *testing.T, argv ...string) []string { return out } -func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { +func TestDeprecatedAliasesStillResolve(t *testing.T) { for _, tc := range []struct{ posture, token string }{ {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, } { @@ -79,7 +79,7 @@ func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { } } -func TestADR_0375_AliasCombinationsStillResolve(t *testing.T) { +func TestAliasCombinationsStillResolve(t *testing.T) { // Headless root: no token grants project trust, so strict plus explicit trust // (today: trusted posture, TrustProject) must keep resolving as it does today. posture, mode, ac := k8sPair(t, "--posture", "strict", "--trust-project") @@ -96,7 +96,7 @@ func TestADR_0375_AliasCombinationsStillResolve(t *testing.T) { } } -func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { +func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { posture, mode, ac := k8sPair(t) if posture != app.PostureAuto || mode != session.ModeDefault { t.Fatalf("default mecak8s = (%s, %s), want (auto, default)", posture, mode) @@ -112,7 +112,7 @@ func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { } } -func TestADR_0375_BareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { +func TestBareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { build := func(argv ...string) error { cfg, err := parseFlags(argv) if err != nil { @@ -139,7 +139,7 @@ func TestADR_0375_BareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { } } -func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { +func TestPermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { _, err := parseFlags([]string{"--permission-mode", "auto", "--posture", "auto"}) if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { t.Fatalf("--permission-mode with --posture err = %v, want a pass-one startup error", err) diff --git a/cmd/mecak8s/telemetry_test.go b/cmd/mecak8s/telemetry_test.go index 8f9b8ac379..0dad3f38f9 100644 --- a/cmd/mecak8s/telemetry_test.go +++ b/cmd/mecak8s/telemetry_test.go @@ -228,7 +228,7 @@ func TestTelemetryMetricsAddrServesPrometheus(t *testing.T) { free := freeLoopbackPort(t) cfg, err := parseFlags([]string{ "--mock", // offline: no provider key in CI - "--guardrails=off", // the auto default must declare its checker choice (ADR 0375) + "--guardrails=off", // the auto default must declare its checker choice "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--metrics-addr", free, @@ -340,7 +340,7 @@ func TestTelemetryPushesRunMetricsOnExit(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", - "--guardrails=off", // the auto default must declare its checker choice (ADR 0375) + "--guardrails=off", // the auto default must declare its checker choice "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--grpc-addr", "127.0.0.1:0", diff --git a/cmd/mecated/main.go b/cmd/mecated/main.go index 291e56d275..8c41a7edbb 100644 --- a/cmd/mecated/main.go +++ b/cmd/mecated/main.go @@ -512,7 +512,7 @@ type config struct { // postureFlagSet is true when --posture was passed explicitly (set after parse via // fs.Visit), so composition lets CLI out-rank the settings.yaml posture: key. postureFlagSet bool - // permissionMode is the raw --permission-mode token (ADR 0375), validated at + // permissionMode is the raw --permission-mode token, validated at // parse time; permissionModeFlagSet records that it was passed explicitly, so // composition (app.Build's foldPermissionMode) lets it out-rank every other // posture source. --posture and --yolo are its deprecated aliases. @@ -1342,7 +1342,7 @@ func appConfig(cfg config, sink port.EventSink, recorder port.ToolCallRecorder, // YAML-only allow-all tier cannot escape it. Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - // Permission mode (ADR 0375): the named token writes both the posture and + // Permission mode: the named token writes both the posture and // the default session mode; app.Build's foldPermissionMode resolves it // ahead of the deprecated --posture/--yolo surface. PermissionMode: cfg.permissionMode, diff --git a/cmd/mecated/permission_mode.go b/cmd/mecated/permission_mode.go index 18734340de..db3c37c779 100644 --- a/cmd/mecated/permission_mode.go +++ b/cmd/mecated/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permissionModeHelp is the --permission-mode usage line (ADR 0375). It names +// permissionModeHelp is the --permission-mode usage line. It names // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + @@ -47,12 +47,12 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { } if cfg.postureFlagSet { diag.Log(context.Background(), port.LevelWarn, - "--posture is DEPRECATED; use --permission-mode instead (ADR 0375)", + "--posture is DEPRECATED; use --permission-mode instead", "posture", cfg.posture, "replacement", "--permission-mode "+postureReplacementToken(cfg.posture)) } if cfg.yoloFlagSet { diag.Log(context.Background(), port.LevelWarn, - "--yolo is DEPRECATED; use --permission-mode yolo instead (ADR 0375)", + "--yolo is DEPRECATED; use --permission-mode yolo instead", "replacement", "--permission-mode yolo") } } diff --git a/cmd/mecated/permission_mode_test.go b/cmd/mecated/permission_mode_test.go index 091497f165..8b500e23af 100644 --- a/cmd/mecated/permission_mode_test.go +++ b/cmd/mecated/permission_mode_test.go @@ -56,7 +56,7 @@ func deprecationWarnings(t *testing.T, argv ...string) []string { return out } -func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { +func TestDeprecatedAliasesStillResolve(t *testing.T) { cases := []struct { name string alias []string @@ -94,7 +94,7 @@ func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { } } -func TestADR_0375_AliasCombinationsStillResolve(t *testing.T) { +func TestAliasCombinationsStillResolve(t *testing.T) { cases := []struct { name string argv []string @@ -129,7 +129,7 @@ func TestADR_0375_AliasCombinationsStillResolve(t *testing.T) { } } -func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { +func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { for _, tc := range []struct { name string argv []string @@ -156,7 +156,7 @@ func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { } } -func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { +func TestPermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { for _, argv := range [][]string{ {"--permission-mode", "auto", "--posture", "auto"}, {"--posture", "strict", "--permission-mode", "default"}, @@ -182,7 +182,7 @@ func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { } } -func TestADR_0375_PermissionModeHitsRootRefusalFastPath(t *testing.T) { +func TestPermissionModeHitsRootRefusalFastPath(t *testing.T) { for _, tok := range []string{"auto", "yolo"} { cfg, err := parseFlags([]string{"--permission-mode", tok}) if err != nil { @@ -202,7 +202,7 @@ func TestADR_0375_PermissionModeHitsRootRefusalFastPath(t *testing.T) { } } -func TestADR_0375_PermissionModeHelpNamesBothHalvesAndEveryToken(t *testing.T) { +func TestPermissionModeHelpNamesBothHalvesAndEveryToken(t *testing.T) { for _, want := range append(app.PermissionModeNames(), "process-wide", "new sessions") { if !strings.Contains(permissionModeHelp, want) { t.Fatalf("--permission-mode help lacks %q: %s", want, permissionModeHelp) diff --git a/cmd/mecatequi/flags.go b/cmd/mecatequi/flags.go index 813c9de804..c4be97aeb6 100644 --- a/cmd/mecatequi/flags.go +++ b/cmd/mecatequi/flags.go @@ -143,7 +143,7 @@ type flags struct { // explicit --posture so composition lets CLI out-rank the settings.yaml key. posture string postureFlagSet bool - // permissionMode is the raw --permission-mode token (ADR 0375), validated at + // permissionMode is the raw --permission-mode token, validated at // parse time; permissionModeFlagSet records it was passed explicitly. permissionMode string permissionModeFlagSet bool @@ -493,7 +493,7 @@ func appConfig(f flags, diag port.Diagnostics, obs observability) app.Config { Posture: app.ParsePosture(f.posture), PostureFlagSet: f.postureFlagSet, - // Permission mode (ADR 0375): an explicit token out-ranks the deprecated + // Permission mode: an explicit token out-ranks the deprecated // --posture in app.Build's foldPermissionMode. PermissionMode: f.permissionMode, PermissionModeFlagSet: f.permissionModeFlagSet, diff --git a/cmd/mecatequi/permission_mode.go b/cmd/mecatequi/permission_mode.go index bc3598ce1c..847baf00ef 100644 --- a/cmd/mecatequi/permission_mode.go +++ b/cmd/mecatequi/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permissionModeHelp is the --permission-mode usage line (ADR 0375). It names +// permissionModeHelp is the --permission-mode usage line. It names // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + @@ -46,6 +46,6 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, f flags) { replacement = tok.Name } diag.Log(context.Background(), port.LevelWarn, - "--posture is DEPRECATED; use --permission-mode instead (ADR 0375)", + "--posture is DEPRECATED; use --permission-mode instead", "posture", f.posture, "replacement", "--permission-mode "+replacement) } diff --git a/cmd/mecatequi/permission_mode_test.go b/cmd/mecatequi/permission_mode_test.go index 22fb1eea2b..e67984d2a4 100644 --- a/cmd/mecatequi/permission_mode_test.go +++ b/cmd/mecatequi/permission_mode_test.go @@ -19,7 +19,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { +func TestDeprecatedAliasesStillResolve(t *testing.T) { for _, tc := range []struct{ posture, token string }{ {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, } { @@ -57,7 +57,7 @@ func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { } } -func TestADR_0375_PermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { +func TestPermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { _, err := parseFlags([]string{"--prompt", "x", "--permission-mode", "auto", "--posture", "auto"}) if err == nil || !strings.Contains(err.Error(), "pass only --permission-mode") { t.Fatalf("--permission-mode with --posture err = %v, want a pass-one startup error", err) @@ -183,12 +183,12 @@ func hasPair(argv []string, flag, value string) bool { return false } -// TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0375 AC2.3 +// TestShippedAllowAllDefaultsDeclareCheckerChoice pins the checker declaration // for the composite action and this repo's live workflow: whenever they run an // allow-all mode they pass a checker model or the explicit --guardrails off, so // the startup refusal never fires on a shipped default. It executes the action's // real bash body against a fake binary rather than grepping it. -func TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { +func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { if _, err := exec.LookPath("bash"); err != nil { t.Skip("bash is required to execute the composite action body") } diff --git a/cmd/mecatui/client/client.go b/cmd/mecatui/client/client.go index 60e053b490..c3f5726246 100644 --- a/cmd/mecatui/client/client.go +++ b/cmd/mecatui/client/client.go @@ -721,7 +721,7 @@ func ModeFromString(s string) mecatlv1.PermissionMode { // RequestModeFromString maps the mode a client REQUESTS for a new session. It is // ModeFromString except that an empty mode means "no preference" and goes out -// UNSPECIFIED, so the server applies its own configured default mode (ADR 0375) +// UNSPECIFIED, so the server applies its own configured default mode // instead of receiving an explicit DEFAULT. func RequestModeFromString(s string) mecatlv1.PermissionMode { if s == "" { diff --git a/cmd/mecatui/config.go b/cmd/mecatui/config.go index 6868f787ac..4ee2caea4a 100644 --- a/cmd/mecatui/config.go +++ b/cmd/mecatui/config.go @@ -238,7 +238,7 @@ type config struct { // key. Mapped onto app.Config.Posture/PostureFlagSet in embeddedConfig. posture string postureFlagSet bool - // permissionMode is the ADR 0375 named token (--permission-mode). It writes the + // permissionMode is the named token (--permission-mode). It writes the // embedded server's posture half (app.Config.PermissionMode) and this client's // requested session mode. modeFlagSet/yoloFlagSet record the deprecated aliases // so the combination error and the one-per-alias deprecation WARN key on what diff --git a/cmd/mecatui/main.go b/cmd/mecatui/main.go index 463f39b081..65ceba1040 100644 --- a/cmd/mecatui/main.go +++ b/cmd/mecatui/main.go @@ -1592,7 +1592,7 @@ func embeddedConfig(cfg config, diag port.Diagnostics) app.Config { // escape it. Posture: app.ParsePosture(cfg.posture), PostureFlagSet: cfg.postureFlagSet, - // ADR 0375 named token: Build resolves its posture half and puts its + // The named permission-mode token: Build resolves its posture half and puts its // session half on the server's DefaultMode. An explicit flag out-ranks the // deprecated --posture and both YAML keys. PermissionMode: cfg.permissionMode, diff --git a/cmd/mecatui/permission_mode.go b/cmd/mecatui/permission_mode.go index 2a6f05b438..06ded56990 100644 --- a/cmd/mecatui/permission_mode.go +++ b/cmd/mecatui/permission_mode.go @@ -10,7 +10,7 @@ import ( "github.com/stacklok/mecatl/internal/app" ) -// permission_mode.go is mecatui's half of the ADR 0375 --permission-mode flag. +// permission_mode.go is mecatui's half of the --permission-mode flag. // A token names an exact (posture, session mode) pair. The posture half goes to // the embedded server's composition (app.Config.PermissionMode); the session half // is the mode this client requests for the sessions it creates. The deprecated diff --git a/cmd/mecatui/permission_mode_test.go b/cmd/mecatui/permission_mode_test.go index 64c6b59108..bf9ae20f9f 100644 --- a/cmd/mecatui/permission_mode_test.go +++ b/cmd/mecatui/permission_mode_test.go @@ -24,10 +24,10 @@ func deprecationLines(cfg config) []string { return strings.Split(out, "\n") } -// TestADR_0375_DeprecatedAliasesStillResolve pins AC6.1 for mecatui: --mode, +// TestDeprecatedAliasesStillResolve pins that, in mecatui, --mode, // --posture, and --yolo resolve exactly as before and each emits exactly one // deprecation WARN naming --permission-mode. --trust-project is not deprecated. -func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { +func TestDeprecatedAliasesStillResolve(t *testing.T) { cases := []struct { name string args []string @@ -94,10 +94,10 @@ func TestADR_0375_DeprecatedAliasesStillResolve(t *testing.T) { }) } -// TestADR_0375_PermissionModeConflictsWithAliases pins that --permission-mode +// TestPermissionModeConflictsWithAliases pins that --permission-mode // combined with any deprecated alias is a startup error telling the operator to // pass one, and that an unknown token fails fast naming the valid set. -func TestADR_0375_PermissionModeConflictsWithAliases(t *testing.T) { +func TestPermissionModeConflictsWithAliases(t *testing.T) { for _, alias := range [][]string{{"--mode", "plan"}, {"--posture", "auto"}, {"--yolo"}} { args := append([]string{"--mock", "--workspace", "/abs", "--permission-mode", "plan"}, alias...) _, _, err := parseTransportFlagsTest(t, modeLocal, args) @@ -117,10 +117,10 @@ func TestADR_0375_PermissionModeConflictsWithAliases(t *testing.T) { } } -// TestADR_0375_ConnectRefusesPostureHalf pins the connect behaviour: the session +// TestConnectRefusesPostureHalf pins the connect behaviour: the session // half of a token applies to this client's sessions, while a non-strict posture // half is refused because the posture belongs to the remote server. -func TestADR_0375_ConnectRefusesPostureHalf(t *testing.T) { +func TestConnectRefusesPostureHalf(t *testing.T) { _, cfg, err := parseTransportFlagsTest(t, modeConnect, []string{"--permission-mode", "accept-edits"}) if err != nil { t.Fatalf("session-only token under connect: %v", err) @@ -139,9 +139,9 @@ func TestADR_0375_ConnectRefusesPostureHalf(t *testing.T) { } } -// TestADR_0375_VocabularyMatchesComposition keeps the TUI's display copy of the +// TestVocabularyMatchesComposition keeps the TUI's display copy of the // token table identical to the composition layer's contract. -func TestADR_0375_VocabularyMatchesComposition(t *testing.T) { +func TestVocabularyMatchesComposition(t *testing.T) { vocab := ui.PermissionModeVocabulary() names := app.PermissionModeNames() if len(vocab) != len(names) { @@ -163,11 +163,11 @@ func TestADR_0375_VocabularyMatchesComposition(t *testing.T) { } } -// TestADR_0375_DefaultsReproduceCurrentBehaviour pins AC6.3 for mecatui end to -// end: the parsed flags build the real embedded server, the real client creates a -// session through the real sessionAdapter, and the server-reported posture and -// session mode match what mecatui produced before ADR 0375. -func TestADR_0375_DefaultsReproduceCurrentBehaviour(t *testing.T) { +// TestDefaultsReproduceCurrentBehaviour pins, for mecatui end to end, that the +// parsed flags build the real embedded server, the real client creates a session +// through the real sessionAdapter, and the server-reported posture and session +// mode match what mecatui produced before the permission-mode vocabulary. +func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { cases := []struct { name string args []string diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 470916b0fd..3c85ef313e 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -159,7 +159,7 @@ func helpBody(th theme.Theme, caps client.Capabilities, hk helpKeys) string { // helpBody renders the overlay body for this model's transport: the permission // mode section's restart guidance differs between the embedded server and -// `mecatui connect` (ADR 0375). +// `mecatui connect`. func (m Model) helpBody() string { return helpBodyFor(m.deps.Theme, m.caps, m.helpKeyMarkings(), m.deps.Embedded) } @@ -310,7 +310,7 @@ func helpBodyFor(th theme.Theme, caps client.Capabilities, hk helpKeys, embedded return b.String() } -// PermissionModeEntry is one row of the ADR 0375 permission-mode vocabulary as +// PermissionModeEntry is one row of the permission-mode vocabulary as // the TUI displays it: the token, the process-wide posture it sets, and the // session mode new sessions start in (the TUI spelling). type PermissionModeEntry struct { @@ -337,7 +337,7 @@ func PermissionModeVocabulary() []PermissionModeEntry { // writeHelpPermissionModes lists every permission-mode token with its two // halves, states that the posture half is process-wide while the session half is // only a new-session default, that cycling the session mode never changes the -// posture, and whose restart a posture change needs (ADR 0375, AC5.2/AC5.5). +// posture, and whose restart a posture change needs. // Runtime selection of a posture from the TUI is deliberately not offered. func writeHelpPermissionModes(b *strings.Builder, th theme.Theme, hk helpKeys, embedded bool) { b.WriteString("\n" + th.Style("toolName").Render("Permission modes (--permission-mode, set at launch)") + "\n") diff --git a/cmd/mecatui/ui/model.go b/cmd/mecatui/ui/model.go index e3d4468ff3..7169ea625b 100644 --- a/cmd/mecatui/ui/model.go +++ b/cmd/mecatui/ui/model.go @@ -295,7 +295,7 @@ type Deps struct { Mode string Model string // ModeServerDefault asks the server to choose the first session's permission - // mode (ADR 0375): no --permission-mode or --mode was given, so the create + // mode: no --permission-mode or --mode was given, so the create // carries an unspecified mode and the server's configured default applies // (embedded: the operator's permissionMode: key; connect: the remote server's // own default). The created session's mode is read back with GetSession, so the diff --git a/cmd/mecatui/ui/permission_mode_adr0375_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go similarity index 84% rename from cmd/mecatui/ui/permission_mode_adr0375_test.go rename to cmd/mecatui/ui/permission_mode_vocabulary_test.go index 338f3deb72..9a838ff534 100644 --- a/cmd/mecatui/ui/permission_mode_adr0375_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -12,8 +12,8 @@ import ( "github.com/stacklok/mecatl/cmd/mecatui/theme" ) -// adr0375Model is a live model bound to a session whose server reports posture. -func adr0375Model(t *testing.T, conv *fakeConv, posture string, embedded bool) Model { +// permissionModeTestModel is a live model bound to a session whose server reports posture. +func permissionModeTestModel(t *testing.T, conv *fakeConv, posture string, embedded bool) Model { t.Helper() m := newTestModelFromDeps(Deps{ Session: conv, @@ -46,12 +46,13 @@ func cycleMode(t *testing.T, m Model) Model { return applyAll(m, cmd()) } -// TestADR_0375_ModeSwitchCycleUnchanged pins AC5.1: the session mode cycle offers -// exactly the three session modes in the same order as before ADR 0375. No -// posture-bearing token becomes reachable from the keybinding. -func TestADR_0375_ModeSwitchCycleUnchanged(t *testing.T) { +// TestModeSwitchCycleUnchanged pins that the session mode cycle offers +// exactly the three session modes in the same order as before the +// permission-mode vocabulary. No posture-bearing token becomes reachable from +// the keybinding. +func TestModeSwitchCycleUnchanged(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0375Model(t, conv, postureStrict, true) + m := permissionModeTestModel(t, conv, postureStrict, true) want := []string{"plan", "accept-edits", "default", "plan"} for range want { m = cycleMode(t, m) @@ -65,16 +66,16 @@ func TestADR_0375_ModeSwitchCycleUnchanged(t *testing.T) { } } -// TestADR_0375_HelpOverlayShowsVocabularyAndScopeSplit pins AC5.2: every token is +// TestHelpOverlayShowsVocabularyAndScopeSplit pins that every token is // listed with its posture half marked process-wide and its session half marked as // the new-session default, with the exact invocation and the statement that // cycling the session mode never changes the posture half. -func TestADR_0375_HelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { +func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0375Model(t, conv, postureStrict, true) + m := permissionModeTestModel(t, conv, postureStrict, true) body := stripANSIstr(m.helpBody()) - // The ADR 0375 table, written out independently of PermissionModeVocabulary. + // The token table, written out independently of PermissionModeVocabulary. want := []struct{ token, posture, session string }{ {"plan", "strict", "plan"}, {"default", "strict", "default"}, @@ -111,10 +112,10 @@ func TestADR_0375_HelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { } } -// TestADR_0375_HeaderShowsPostureWhenAboveStrict pins AC5.3: the header shows the +// TestHeaderShowsPostureWhenAboveStrict pins that the header shows the // session mode, and a posture badge for every tier above strict (trusted now // included), sourced from the server-reported caps.Posture. -func TestADR_0375_HeaderShowsPostureWhenAboveStrict(t *testing.T) { +func TestHeaderShowsPostureWhenAboveStrict(t *testing.T) { cases := []struct { posture string badge string // "" = no badge @@ -127,7 +128,7 @@ func TestADR_0375_HeaderShowsPostureWhenAboveStrict(t *testing.T) { for _, tc := range cases { t.Run(tc.posture, func(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0375Model(t, conv, tc.posture, true) + m := permissionModeTestModel(t, conv, tc.posture, true) header := stripANSIstr(m.renderHeader()) if got := statusMode(m); got != "default" { t.Errorf("status mode = %q, want default", got) @@ -146,12 +147,12 @@ func TestADR_0375_HeaderShowsPostureWhenAboveStrict(t *testing.T) { } } -// TestADR_0375_HeaderKeepsPostureAcrossModeCycle pins AC5.4: under auto, cycling +// TestHeaderKeepsPostureAcrossModeCycle pins that under auto, cycling // the session mode through plan and back to default keeps the auto badge on every // frame, including the pending frame before the server confirms each switch. -func TestADR_0375_HeaderKeepsPostureAcrossModeCycle(t *testing.T) { +func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0375Model(t, conv, postureAuto, true) + m := permissionModeTestModel(t, conv, postureAuto, true) assertAuto := func(step, wantMode string) { t.Helper() header := stripANSIstr(m.renderHeader()) @@ -175,13 +176,13 @@ func TestADR_0375_HeaderKeepsPostureAcrossModeCycle(t *testing.T) { } } -// TestADR_0375_HelpOverlayNamesWhoseRestart pins AC5.5: the embedded server's +// TestHelpOverlayNamesWhoseRestart pins that the embedded server's // help gives the mecatui relaunch invocation; under `mecatui connect` it names // the server operator's mecated restart and offers no local invocation. -func TestADR_0375_HelpOverlayNamesWhoseRestart(t *testing.T) { +func TestHelpOverlayNamesWhoseRestart(t *testing.T) { render := func(embedded bool) string { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := adr0375Model(t, conv, postureAuto, embedded) + m := permissionModeTestModel(t, conv, postureAuto, embedded) return stripANSIstr(m.helpBody()) } embedded := render(true) @@ -200,7 +201,7 @@ func TestADR_0375_HelpOverlayNamesWhoseRestart(t *testing.T) { } } -// TestModeServerDefaultRequestsUnspecifiedAndReadsBack pins the ADR 0375 session +// TestModeServerDefaultRequestsUnspecifiedAndReadsBack pins the session // half under ModeServerDefault: the first create requests no mode, so the server's // default applies, and the header shows the mode the server reports rather than // guessing "default". diff --git a/cmd/mecatui/ui/posture_badge_test.go b/cmd/mecatui/ui/posture_badge_test.go index 0872dd302e..01555e74e2 100644 --- a/cmd/mecatui/ui/posture_badge_test.go +++ b/cmd/mecatui/ui/posture_badge_test.go @@ -13,7 +13,7 @@ import ( // TestPostureBadgeShownForAutoYolo asserts the header renders the auto/yolo chrome // badge when the server reports an allow-all posture, the quieter trusted badge for -// trusted (ADR 0375), and NO badge for strict (and an empty/older-server posture) — +// trusted, and NO badge for strict (and an empty/older-server posture) — // the goldens-stability guarantee. Under // MECATUI_NO_EMOJI the yolo badge is the clean " YOLO " pill with NO lightning bolt and // NO VS16; auto is "⚠ auto". The badge is sourced from caps.Posture (SessionReadyMsg), diff --git a/cmd/mecatui/ui/view.go b/cmd/mecatui/ui/view.go index 27147f3527..7c37d949fb 100644 --- a/cmd/mecatui/ui/view.go +++ b/cmd/mecatui/ui/view.go @@ -209,7 +209,7 @@ const yoloBoltPrefix = "⚡️ " // fit/shed math. It surfaces the SERVER-WIDE posture (m.caps.Posture) whenever it is // above strict — strict/unknown render NO badge, so the steady-state frame and the // goldens stay byte-identical. It is DISTINCT from the per-session `mode` segment, and a -// session-mode cycle never changes it (ADR 0375). +// session-mode cycle never changes it. // // Tiers: // - trusted → warning-styled inline text "trusted". @@ -236,7 +236,7 @@ func (m Model) postureBadgeRender() (styled string, plainWidth int) { } return pill, w case postureTrusted: - // Above strict (ADR 0375, AC5.3): the project's rules and instructions are + // Above strict: the project's rules and instructions are // honoured process-wide, so the header must not read as a plain default // session. Warning-styled text, no glyph, quieter than auto's. return m.deps.Theme.Style("warning").Render(trustedBadgeText), lipgloss.Width(trustedBadgeText) diff --git a/deploy/helm/mecak8s/chart_test.go b/deploy/helm/mecak8s/chart_test.go index 00c58d8982..7f3ef4651e 100644 --- a/deploy/helm/mecak8s/chart_test.go +++ b/deploy/helm/mecak8s/chart_test.go @@ -3074,12 +3074,12 @@ mcp: } } -// TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice pins ADR 0375 AC2.3 for +// TestShippedAllowAllDefaultsDeclareCheckerChoice pins the checker declaration for // the chart: it runs mecak8s in the allow-all auto permission mode, and mecak8s // refuses that mode without a checker, so every render must declare the checker // choice. An empty guardrails.model is the explicit unsupervised --guardrails=off; // a set model becomes --guardrails-model and never carries the kill-switch. -func TestADR_0375_ShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { +func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { cases := []struct { name string extra []string diff --git a/internal/adapter/permconfig/resolve.go b/internal/adapter/permconfig/resolve.go index c58b47b317..d266c33f02 100644 --- a/internal/adapter/permconfig/resolve.go +++ b/internal/adapter/permconfig/resolve.go @@ -139,7 +139,7 @@ type Resolver struct { // files) out-ranks user-global (first-non-empty keeps CLI). operatorPosture string - // operatorPermissionMode is the OPERATOR-TIER permissionMode: token (ADR 0375), + // operatorPermissionMode is the OPERATOR-TIER permissionMode: token, // captured exactly like operatorPosture: user-global + CLI tiers only, CLI // first-non-empty wins, a project-tier occurrence is ignored with a WARN. operatorPermissionMode string @@ -1087,9 +1087,8 @@ func (r *Resolver) warnIgnoredProjectPermissionScalars(cfg *Config, path, root s "posture: IGNORING a project-tier posture: scalar (operator-tier only — a project repo cannot raise the automation posture; set permissionMode in your user-global settings.yaml or via --permission-mode)", "file", path, "root", root) } - // PermissionMode is OPERATOR-TIER ONLY for the same reason as posture (ADR - // 0375): a repo naming its own permission mode could raise the automation - // posture. + // PermissionMode is OPERATOR-TIER ONLY for the same reason as posture: a + // repo naming its own permission mode could raise the automation posture. if strings.TrimSpace(cfg.PermissionMode) != "" { r.diag.Log(context.Background(), port.LevelWarn, "permissionMode: IGNORING a project-tier permissionMode: scalar (operator-tier only — a project repo cannot choose its own permission mode; set permissionMode in your user-global settings.yaml or via --permission-mode)", diff --git a/internal/adapter/permconfig/schema.go b/internal/adapter/permconfig/schema.go index 8184d39ccb..b60b8a7963 100644 --- a/internal/adapter/permconfig/schema.go +++ b/internal/adapter/permconfig/schema.go @@ -165,8 +165,8 @@ type Config struct { // keeps the CLI/default). The composition layer parses the string; permconfig only // reads the scalar. Posture string `yaml:"posture"` - // PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0375: - // plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets + // PermissionMode is the OPERATOR-TIER named permission-mode token + // (plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets // the posture and the default session mode together and supersedes the // deprecated posture: key. Like Posture it is honoured ONLY from the // user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. diff --git a/internal/adapter/server/default_mode_test.go b/internal/adapter/server/default_mode_test.go index 1755d0d17e..30885797c5 100644 --- a/internal/adapter/server/default_mode_test.go +++ b/internal/adapter/server/default_mode_test.go @@ -17,7 +17,7 @@ import ( // TestGRPCCreateSessionUnspecifiedModeUsesServerDefault pins that a gRPC // CreateSession leaving mode UNSPECIFIED starts in the server's configured -// DefaultMode (the session half of the operator's permission mode, ADR 0375), +// DefaultMode (the session half of the operator's permission mode), // while an explicit mode still wins. func TestGRPCCreateSessionUnspecifiedModeUsesServerDefault(t *testing.T) { llm := mockllm.New() diff --git a/internal/adapter/server/mapper.go b/internal/adapter/server/mapper.go index e88569e865..1869526842 100644 --- a/internal/adapter/server/mapper.go +++ b/internal/adapter/server/mapper.go @@ -1407,8 +1407,8 @@ func modeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { // createModeFromProto maps a CreateSession mode. Unlike modeFromProto, an // UNSPECIFIED mode stays empty so Service.createSession applies the server's -// configured DefaultMode (the session half of the operator's permission mode, -// ADR 0375), matching the HTTP create path. +// configured DefaultMode (the session half of the operator's permission mode), +// matching the HTTP create path. func createModeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { if m == mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { return "" diff --git a/internal/app/build.go b/internal/app/build.go index c4d553d196..2b9878638e 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -1081,7 +1081,7 @@ type Config struct { // (CLI out-ranks YAML) and resolvePosture WARNs if an alias raised above the // explicit value. Set by the cmd mains alongside Posture. PostureFlagSet bool - // PermissionMode is the raw --permission-mode token (ADR 0375), meaningful only + // PermissionMode is the raw --permission-mode token, meaningful only // when PermissionModeFlagSet. foldPermissionMode resolves it (or the // operator-tier permissionMode: key) into Posture + DefaultSessionMode; an // unknown token is a Build error naming the valid set. @@ -1098,7 +1098,7 @@ type Config struct { // foldPermissionMode; empty when only the deprecated surface was used. permissionModeName string // askReviewerDefaultOn is set by resolveAskReviewerDefault when the headless - // allow-all default engages the subagent ask reviewer (ADR 0375 decision 6). + // allow-all default engages the subagent ask reviewer. askReviewerDefaultOn bool // askReviewerOptOut records an explicit --subagent-ask-reviewer off. askReviewerOptOut bool @@ -1725,7 +1725,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.TrustProject = trust.Trusted narratePosture(cfg.diag(), cfg.Posture, cfg.TrustProject) narrateTrust(cfg.diag(), trust, cfg.Workspace) - // Headless admission gate (ADR 0375): after the trust fold, so every + // Headless admission gate: after the trust fold, so every // legitimate trust source satisfies it. if err := headlessTrustRefusal(cfg); err != nil { return nil, err @@ -2092,7 +2092,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg.guardrailModel = guardrailModel cfg.guardrailSource = guardrailSrc cfg.guardrailConfigured = guardrailConfigured - // Allow-all admission gate (ADR 0375): the checker truth is the SAME the + // Allow-all admission gate: the checker truth is the SAME the // posture line and the live checker use (the binding, else the resolver). checkerConfigured := guardrailConfigured if !checkerConfigured { @@ -2448,7 +2448,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { mcpStatus = assets.mcpReconciler.statusSnapshot } svcCfg := server.Config{ - // The session half of the permission-mode token (ADR 0375): the mode a + // The session half of the permission-mode token: the mode a // CreateSession that leaves mode unspecified starts in. Empty keeps the // server's own ModeDefault. DefaultMode: cfg.DefaultSessionMode, @@ -7488,7 +7488,7 @@ func askAdjudicatorDeps(cfg Config, provReg *providerRegistry, provider port.LLM // The --subagent-ask-reviewer flag STAYS the enable gate: a slot alone does // NOT turn the reviewer on (a slot only chooses the model for a reviewer the // operator already enabled). Empty flag ⇒ reviewer off, byte-identical — - // except the ADR 0375 headless allow-all default (askReviewerDefaultOn), + // except the headless allow-all default (askReviewerDefaultOn), // which resolves through the slot, then the parent model, below. return agent.Deps{}, false } diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index b527f86f52..1486990ed1 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -12,7 +12,7 @@ import ( ) // permission_mode.go is the COMPOSITION-LAYER named permission-mode vocabulary -// (ADR 0375). A token is an operator shorthand that writes an exact pair of +//. A token is an operator shorthand that writes an exact pair of // EXISTING values: the process-wide Posture and the default session // PermissionMode (server.Config.DefaultMode). It introduces no third source of // permission state: the table below is the whole mechanism, and it is a lookup, @@ -31,7 +31,7 @@ type PermissionModeToken struct { SessionMode session.PermissionMode } -// permissionModeTable is the ADR 0375 contract. Redundant products (an +// permissionModeTable is the token contract. Redundant products (an // accept-edits variant of auto or yolo) are deliberately absent: allow-all // already permits edits. var permissionModeTable = []PermissionModeToken{ @@ -120,7 +120,7 @@ func foldPermissionMode(cfg Config) (Config, error) { return cfg, nil } -// checkerRefusal is the allow-all admission gate (ADR 0375 decision 4). A +// checkerRefusal is the allow-all admission gate. A // posture that waives the built-in mutate-ask floor leaves the guardrails // checker as the only inspection of tool content, so starting one with no // checker and no explicit kill-switch is refused. It keys on the RESOLVED @@ -143,7 +143,7 @@ func checkerRefusal(cfg Config, checkerConfigured bool) error { // refusal and the startup line so they cannot disagree. const yoloCheckerAdvisoryNote = "At yolo a configured checker is observability-only: it has no pre-tool veto, no approve-once human ask, and no fail-closed on checker failure, so a checker outage looks the same as a clean result" -// headlessTrustRefusal is the headless admission gate (ADR 0375 decision 5). +// headlessTrustRefusal is the headless admission gate. // It runs AFTER resolveTrust, so any legitimate trust source satisfies it, and // applies only to the trust-naming posture: trust is not auto's or yolo's // defining increment, so those WARN instead (narrateWithheldTrust). @@ -156,7 +156,7 @@ func headlessTrustRefusal(cfg Config) error { } // narrateWithheldTrust WARNs when a headless allow-all root starts without -// project trust: it is a legitimate production state (ADR 0095), but the +// project trust: it is a legitimate production state, but the // operator should see that project instructions and rules are not loaded. func narrateWithheldTrust(cfg Config) { if !cfg.Headless || cfg.Posture < PostureAuto || cfg.TrustProject { @@ -184,7 +184,7 @@ func (cfg Config) resolvedPermissionModeName() string { return fmt.Sprintf("posture %s with session mode %s", cfg.Posture, mode) } -// The three checker states the startup line reports (ADR 0375 AC2.6). +// The three checker states the startup line reports. const ( checkerEnforcing = "enforcing" checkerAdvisory = "advisory" @@ -192,7 +192,7 @@ const ( ) // checkerState reports the guardrails checker as exactly one of three named -// states (ADR 0375 AC2.6), plus the reason when it is disabled. +// states, plus the reason when it is disabled. func checkerState(cfg Config, configured bool) (state, reason string) { switch { case cfg.GuardrailsDisabled: @@ -227,7 +227,7 @@ func reviewerState(cfg Config) string { // narratePermissionMode is the ONE build-once line reporting the resolved token, // both halves it set with their lifetimes, and the checker and reviewer states -// as separately scannable items (ADR 0375 AC5.6). The reviewer and the checker +// as separately scannable items. The reviewer and the checker // are different mechanisms and are named separately; neither is described in // the other's terms. func narratePermissionMode(cfg Config, checkerConfigured bool) { @@ -265,7 +265,7 @@ func isAskReviewerOptOut(s string) bool { } // resolveAskReviewerDefault decides whether the headless subagent ask reviewer -// is on by default (ADR 0375 decision 6): headless (no human approver), an +// is on by default: headless (no human approver), an // allow-all posture, no explicit reviewer model, and no explicit opt-out. It // resolves its model through the existing ask-reviewer slot with the // parent-model fallback; when neither resolves, behaviour stays today's diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index 71b93483e2..373a113682 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -15,7 +15,7 @@ import ( "github.com/stacklok/mecatl/internal/adapter/permconfig" ) -// permissionModeCfg is the offline Build fixture for the ADR 0375 tests: an +// permissionModeCfg is the offline Build fixture for the permission-mode tests: an // explicit --permission-mode token over the mock provider. func permissionModeCfg(t *testing.T, token string, diag port.Diagnostics) Config { t.Helper() @@ -41,7 +41,7 @@ func builtDefaultSessionMode(t *testing.T, built *Built) session.PermissionMode return sess.Mode } -func TestADR_0375_TokenTableResolvesExactPairs(t *testing.T) { +func TestTokenTableResolvesExactPairs(t *testing.T) { want := map[string]struct { posture Posture mode session.PermissionMode @@ -55,7 +55,7 @@ func TestADR_0375_TokenTableResolvesExactPairs(t *testing.T) { "yolo": {PostureYolo, session.ModeDefault}, } if got := PermissionModeNames(); len(got) != len(want) { - t.Fatalf("token set = %v, want exactly the %d ADR tokens", got, len(want)) + t.Fatalf("token set = %v, want exactly the %d tokens", got, len(want)) } for name, pair := range want { tok, err := ParsePermissionMode(name) @@ -96,7 +96,7 @@ func TestADR_0375_TokenTableResolvesExactPairs(t *testing.T) { } } -func TestADR_0375_TrustedKeepsCurrentMeaning(t *testing.T) { +func TestTrustedKeepsCurrentMeaning(t *testing.T) { cfg := permissionModeCfg(t, "trusted", port.NopDiagnostics{}) legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, Posture: PostureTrusted, PostureFlagSet: true} for name, c := range map[string]Config{"token": cfg, "--posture trusted": legacy} { @@ -114,7 +114,7 @@ func TestADR_0375_TrustedKeepsCurrentMeaning(t *testing.T) { } } -func TestADR_0375_TrustedAcceptEditsIsNameable(t *testing.T) { +func TestTrustedAcceptEditsIsNameable(t *testing.T) { built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", port.NopDiagnostics{})) if err != nil { t.Fatalf("Build: %v", err) @@ -128,7 +128,7 @@ func TestADR_0375_TrustedAcceptEditsIsNameable(t *testing.T) { } } -func TestADR_0375_AllowAllTokenRequiresChecker(t *testing.T) { +func TestAllowAllTokenRequiresChecker(t *testing.T) { for _, token := range []string{"auto", "yolo"} { _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) if err == nil { @@ -157,7 +157,7 @@ func TestADR_0375_AllowAllTokenRequiresChecker(t *testing.T) { } } -func TestADR_0375_CheckerRefusalNamesEveryFix(t *testing.T) { +func TestCheckerRefusalNamesEveryFix(t *testing.T) { _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "auto", port.NopDiagnostics{})) if err == nil { t.Fatal("auto with no checker must refuse") @@ -169,7 +169,7 @@ func TestADR_0375_CheckerRefusalNamesEveryFix(t *testing.T) { } } -func TestADR_0375_GateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { +func TestGateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { properties := []string{"pre-tool veto", "approve-once human ask", "fail-closed"} _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "yolo", port.NopDiagnostics{})) @@ -201,7 +201,7 @@ func TestADR_0375_GateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { } } -func TestADR_0375_NonAllowAllTokensRequireNoChecker(t *testing.T) { +func TestNonAllowAllTokensRequireNoChecker(t *testing.T) { for _, token := range []string{"plan", "default", "accept-edits", "trusted", "trusted-accept-edits"} { built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) if err != nil { @@ -211,7 +211,7 @@ func TestADR_0375_NonAllowAllTokensRequireNoChecker(t *testing.T) { } } -func TestADR_0375_StartupLineNamesCheckerState(t *testing.T) { +func TestStartupLineNamesCheckerState(t *testing.T) { cases := []struct { name string cfg Config @@ -251,7 +251,7 @@ func headlessCfg(t *testing.T, token string, diag port.Diagnostics) Config { return cfg } -func TestADR_0375_HeadlessTrustTokenRefused(t *testing.T) { +func TestHeadlessTrustTokenRefused(t *testing.T) { for _, token := range []string{"trusted", "trusted-accept-edits"} { _, err := buildIsolated(t, context.Background(), headlessCfg(t, token, port.NopDiagnostics{})) if err == nil { @@ -265,7 +265,7 @@ func TestADR_0375_HeadlessTrustTokenRefused(t *testing.T) { } } -func TestADR_0375_HeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { +func TestHeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { t.Run("explicit --trust-project", func(t *testing.T) { cfg := headlessCfg(t, "trusted", port.NopDiagnostics{}) cfg.TrustProject = true @@ -289,7 +289,7 @@ func TestADR_0375_HeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { }) } -func TestADR_0375_HeadlessAllowAllStartsWithoutTrust(t *testing.T) { +func TestHeadlessAllowAllStartsWithoutTrust(t *testing.T) { for _, token := range []string{"auto", "yolo"} { rec := slogdiagBuffer(t) cfg := headlessCfg(t, token, rec.diag) @@ -308,7 +308,7 @@ func TestADR_0375_HeadlessAllowAllStartsWithoutTrust(t *testing.T) { } } -func TestADR_0375_InteractiveTrustTokenGrantsTrust(t *testing.T) { +func TestInteractiveTrustTokenGrantsTrust(t *testing.T) { withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted", rec.diag)) @@ -324,7 +324,7 @@ func TestADR_0375_InteractiveTrustTokenGrantsTrust(t *testing.T) { } } -func TestADR_0375_AllowAllNarratesSubagentAsymmetry(t *testing.T) { +func TestAllowAllNarratesSubagentAsymmetry(t *testing.T) { rec := slogdiagBuffer(t) cfg := permissionModeCfg(t, "auto", rec.diag) cfg.GuardrailsDisabled = true @@ -347,7 +347,7 @@ func headlessAllowAll(t *testing.T, diag port.Diagnostics) Config { return cfg } -func TestADR_0375_HeadlessAllowAllDefaultsReviewerOn(t *testing.T) { +func TestHeadlessAllowAllDefaultsReviewerOn(t *testing.T) { rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), headlessAllowAll(t, rec.diag)) if err != nil { @@ -375,7 +375,7 @@ func TestADR_0375_HeadlessAllowAllDefaultsReviewerOn(t *testing.T) { } } -func TestADR_0375_ReviewerDefaultIsOptOutAndNarrated(t *testing.T) { +func TestReviewerDefaultIsOptOutAndNarrated(t *testing.T) { rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), headlessAllowAll(t, rec.diag)) if err != nil { @@ -405,7 +405,7 @@ func TestADR_0375_ReviewerDefaultIsOptOutAndNarrated(t *testing.T) { } } -func TestADR_0375_ReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { +func TestReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { rec := slogdiagBuffer(t) cfg := resolveAskReviewerDefault(Config{Posture: PostureAuto, Diagnostics: rec.diag}) if cfg.askReviewerDefaultOn { @@ -419,7 +419,7 @@ func TestADR_0375_ReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { } } -func TestADR_0375_ReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { +func TestReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { for name, cfg := range map[string]Config{ "interactive auto": {Posture: PostureAuto, Interactive: true, Model: "m"}, "headless strict": {Posture: PostureStrict, Model: "m"}, @@ -432,7 +432,7 @@ func TestADR_0375_ReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { } } -func TestADR_0375_ReviewerAndCheckerNarratedSeparately(t *testing.T) { +func TestReviewerAndCheckerNarratedSeparately(t *testing.T) { rec := slogdiagBuffer(t) cfg := headlessCfg(t, "auto", rec.diag) cfg.GuardrailsModel = "mock-checker" @@ -456,7 +456,7 @@ func TestADR_0375_ReviewerAndCheckerNarratedSeparately(t *testing.T) { } } -func TestADR_0375_StartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing.T) { +func TestStartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing.T) { rec := slogdiagBuffer(t) built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", rec.diag)) if err != nil { @@ -482,7 +482,7 @@ func TestADR_0375_StartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing } } -func TestADR_0375_PermissionModeIsOperatorTierOnly(t *testing.T) { +func TestPermissionModeIsOperatorTierOnly(t *testing.T) { operatorFile := func(t *testing.T, token string) string { t.Helper() path := filepath.Join(t.TempDir(), "operator.yaml") @@ -574,7 +574,7 @@ func TestADR_0375_PermissionModeIsOperatorTierOnly(t *testing.T) { } // TestInvariant_NoWireOrDomainSurfaceChanged pins that the vocabulary added no -// session-selectable value (ADR 0375 decision 3): the domain keeps its three +// session-selectable value: the domain keeps its three // modes with their strings, the proto enum keeps its four values, and an old // snapshot's mode string still round-trips. `task api:check` covers the engine // API surface itself. @@ -598,10 +598,10 @@ func TestInvariant_NoWireOrDomainSurfaceChanged(t *testing.T) { } } -// TestADR_0375_AuthoritativePostureFoldsPermissionModeKey pins that the cmd +// TestAuthoritativePostureFoldsPermissionModeKey pins that the cmd // fast paths (root refusal, pre-launch WARN) see an operator-YAML-only // permissionMode: allow-all token, not only an explicit flag. -func TestADR_0375_AuthoritativePostureFoldsPermissionModeKey(t *testing.T) { +func TestAuthoritativePostureFoldsPermissionModeKey(t *testing.T) { path := filepath.Join(t.TempDir(), "operator.yaml") if err := os.WriteFile(path, []byte("permissionMode: yolo\n"), 0o600); err != nil { t.Fatal(err) diff --git a/internal/app/posture.go b/internal/app/posture.go index e47ebb3a82..a9a3fe2930 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -261,7 +261,7 @@ func foldOperatorPosture(cfg Config) Config { } cfg.Posture = parsePosture(yamlPosture) cfg.diag().Log(context.Background(), port.LevelWarn, - "posture: the settings.yaml posture: key is DEPRECATED; use permissionMode: instead (ADR 0375)", + "posture: the settings.yaml posture: key is DEPRECATED; use permissionMode: instead", "posture", yamlPosture) return cfg } @@ -275,7 +275,7 @@ func foldOperatorPosture(cfg Config) Config { // decision drive the real Build and read its structured diagnostic. func ResolveAuthoritativePosture(cfg Config) Posture { cfg.permResolver = buildPermResolver(cfg) - // Fold the permission-mode token first (ADR 0375), so an operator-YAML-only + // Fold the permission-mode token first, so an operator-YAML-only // permissionMode: auto/yolo reaches the cmd fast paths. An invalid token is // Build's to report; the pre-check falls back to the deprecated surface. if folded, err := foldPermissionMode(cfg); err == nil { diff --git a/internal/configgen/build.go b/internal/configgen/build.go index cdadad80af..eae827a6ac 100644 --- a/internal/configgen/build.go +++ b/internal/configgen/build.go @@ -403,7 +403,7 @@ func permissionModeSubtree(docs Docs) *Subtree { return &Subtree{ Key: "permissionMode", Tier: TierOperator, - Doc: "OPERATOR-TIER named permission mode (ADR 0375): plan, default, accept-edits, trusted, " + + Doc: "OPERATOR-TIER named permission mode: plan, default, accept-edits, trusted, " + "trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, " + "fixed at startup, and the mode new sessions start in, which each session may change. auto " + "and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. " + @@ -425,7 +425,7 @@ func postureSubtree(docs Docs) *Subtree { return &Subtree{ Key: "posture", Tier: TierOperator, - Doc: "DEPRECATED: use permissionMode: instead (ADR 0375); still honoured with a WARN for one release. " + + Doc: "DEPRECATED: use permissionMode: instead; still honoured with a WARN for one release. " + "OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated " + "trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project " + "cannot raise the automation posture). Empty = keep the CLI/default.", diff --git a/internal/configgen/configgen_test.go b/internal/configgen/configgen_test.go index 182c9f5d68..db3d005edb 100644 --- a/internal/configgen/configgen_test.go +++ b/internal/configgen/configgen_test.go @@ -110,7 +110,7 @@ func authoritativeKeys() []string { collect("mcp.servers.auth.oauth.tools", permconfig.MCPStaticToolProfile{}) // posture is a bare scalar Config field, not a *Section. keys = append(keys, "posture") - // permissionMode is likewise a bare scalar Config field (ADR 0375). + // permissionMode is likewise a bare scalar Config field. keys = append(keys, "permissionMode") // output-economy is absent: the setting was REMOVED (a // clean break) and MUST NOT appear in generated artifacts (pinned by @@ -368,7 +368,7 @@ func TestSubtreeTiersAreAsPinned(t *testing.T) { "permissions": configgen.TierProject, // allow/ask/deny + subagent: project-settable (allows trust-gated) "guardrails": configgen.TierOperator, // operator-only: a project cannot weaken a security checker "posture": configgen.TierOperator, // operator-only: a project cannot raise the automation posture - "permissionMode": configgen.TierOperator, // operator-only: a project cannot choose its own permission mode (ADR 0375) + "permissionMode": configgen.TierOperator, // operator-only: a project cannot choose its own permission mode "reasoning-effort": configgen.TierOperator, // operator-only: a project cannot raise the model's reasoning spend "plan-mode-auto-approve": configgen.TierOperator, // operator-only: a project cannot grant an autonomous approval capability (issue #206) "providers": configgen.TierOperator, // operator-only: a project cannot choose LLM endpoints or auth posture diff --git a/internal/configgen/settings.skeleton.yaml b/internal/configgen/settings.skeleton.yaml index 6c21047dec..4f4ed238e9 100644 --- a/internal/configgen/settings.skeleton.yaml +++ b/internal/configgen/settings.skeleton.yaml @@ -97,7 +97,7 @@ # failClosed: false #| === permissionMode === (tier: operator) -#| OPERATOR-TIER named permission mode (ADR 0375): plan, default, accept-edits, trusted, +#| OPERATOR-TIER named permission mode: plan, default, accept-edits, trusted, #| trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide #| posture, fixed at startup, and the mode new sessions start in, which each session may #| change. auto and yolo refuse to start without a guardrails checker unless guardrails @@ -107,10 +107,10 @@ # permissionMode: trusted-accept-edits #| === posture === (tier: operator) -#| DEPRECATED: use permissionMode: instead (ADR 0375); still honoured with a WARN for -#| one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the -#| graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a -#| project cannot raise the automation posture). Empty = keep the CLI/default. +#| DEPRECATED: use permissionMode: instead; still honoured with a WARN for one release. +#| OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated +#| trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project +#| cannot raise the automation posture). Empty = keep the CLI/default. # posture: trusted #| === reasoning-effort === (tier: operator) diff --git a/user-docs/reference/configuration.md b/user-docs/reference/configuration.md index 1f00f6ea28..55a3376fb5 100644 --- a/user-docs/reference/configuration.md +++ b/user-docs/reference/configuration.md @@ -78,17 +78,17 @@ OPERATOR-TIER LLM content-checker (issue #27). Parsed strictly. A project-tier g Tier: **operator** -OPERATOR-TIER named permission mode (ADR 0375): plan, default, accept-edits, trusted, trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, fixed at startup, and the mode new sessions start in, which each session may change. auto and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. +OPERATOR-TIER named permission mode: plan, default, accept-edits, trusted, trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, fixed at startup, and the mode new sessions start in, which each session may change. auto and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. | Value | Type | Default | Description | | --- | --- | --- | --- | -| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (ADR 0375: plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets the posture and the default session mode together and supersedes the deprecated posture: key. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | +| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets the posture and the default session mode together and supersedes the deprecated posture: key. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | ## `posture` Tier: **operator** -DEPRECATED: use permissionMode: instead (ADR 0375); still honoured with a WARN for one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project cannot raise the automation posture). Empty = keep the CLI/default. +DEPRECATED: use permissionMode: instead; still honoured with a WARN for one release. OPERATOR-TIER posture-ladder scalar: strict < trusted < auto < yolo (the graduated trust/automation tier). A project-tier posture: is IGNORED with a WARN (a project cannot raise the automation posture). Empty = keep the CLI/default. | Value | Type | Default | Description | | --- | --- | --- | --- | From 64da9e0986fa08be621b9be5bcc5e5086fec38c8 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Thu, 8 Oct 2026 17:11:28 +0300 Subject: [PATCH 15/48] feat(mecatui): cycle every permission mode and block ones that need a restart shift+tab now walks all seven permission modes. A mode at or below the running posture applies its session half live; one that would raise the posture is blocked, because the posture is fixed at server start. While blocked, the header shows "mode blocked", the prompt area says what to configure and how to relaunch, typing/sending/pasting and the queued drain are held with the draft kept, and esc returns to the running mode. Co-authored-by: Mecatl --- cmd/mecatui/client/client.go | 12 - cmd/mecatui/client/models_test.go | 14 -- cmd/mecatui/ui/help.go | 11 +- cmd/mecatui/ui/keys.go | 5 +- cmd/mecatui/ui/mode_cycle.go | 221 +++++++++++++++++ cmd/mecatui/ui/model.go | 3 + .../ui/permission_mode_vocabulary_test.go | 233 ++++++++++++++++-- cmd/mecatui/ui/statusline_source.go | 8 +- cmd/mecatui/ui/testdata/help_all_on.golden | 2 +- cmd/mecatui/ui/testdata/help_embedded.golden | 2 +- cmd/mecatui/ui/update.go | 32 ++- cmd/mecatui/ui/view.go | 13 + .../permissions-and-posture.md | 37 ++- user-docs/mecatui/keybindings.md | 2 +- user-docs/mecatui/using-the-tui.md | 8 +- 15 files changed, 517 insertions(+), 86 deletions(-) create mode 100644 cmd/mecatui/ui/mode_cycle.go diff --git a/cmd/mecatui/client/client.go b/cmd/mecatui/client/client.go index c3f5726246..df51237d25 100644 --- a/cmd/mecatui/client/client.go +++ b/cmd/mecatui/client/client.go @@ -745,18 +745,6 @@ func ModeString(m mecatlv1.PermissionMode) string { } } -// NextMode returns the next mode in the TUI's cycle order. -func NextMode(mode string) string { - switch ModeString(ModeFromString(mode)) { - case ModeDefaultString: - return modePlanString - case modePlanString: - return "accept-edits" - default: - return ModeDefaultString - } -} - // loadCAPool reads a PEM CA bundle into a cert pool for server verification. func loadCAPool(path string) (*x509.CertPool, error) { pem, err := os.ReadFile(path) //nolint:gosec // operator-supplied CA path diff --git a/cmd/mecatui/client/models_test.go b/cmd/mecatui/client/models_test.go index ab0100092c..219c1a7d78 100644 --- a/cmd/mecatui/client/models_test.go +++ b/cmd/mecatui/client/models_test.go @@ -297,18 +297,4 @@ func TestModeHelpers(t *testing.T) { if got := ModeString(ModeFromString("accept-edits")); got != "accept-edits" { t.Fatalf("accept-edits round trip = %q", got) } - cases := []struct { - in string - want string - }{ - {"default", "plan"}, - {"plan", "accept-edits"}, - {"accept-edits", "default"}, - {"", "plan"}, - } - for _, tc := range cases { - if got := NextMode(tc.in); got != tc.want { - t.Errorf("NextMode(%q) = %q, want %q", tc.in, got, tc.want) - } - } } diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 3c85ef313e..840187b56b 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -336,11 +336,10 @@ func PermissionModeVocabulary() []PermissionModeEntry { // writeHelpPermissionModes lists every permission-mode token with its two // halves, states that the posture half is process-wide while the session half is -// only a new-session default, that cycling the session mode never changes the -// posture, and whose restart a posture change needs. -// Runtime selection of a posture from the TUI is deliberately not offered. +// only a new-session default, that cycling reaches every mode but cannot raise +// the posture, and whose restart a posture change needs. func writeHelpPermissionModes(b *strings.Builder, th theme.Theme, hk helpKeys, embedded bool) { - b.WriteString("\n" + th.Style("toolName").Render("Permission modes (--permission-mode, set at launch)") + "\n") + b.WriteString("\n" + th.Style("toolName").Render("Permission modes (--permission-mode, or cycle with "+hk.modeSwitch+")") + "\n") vocab := PermissionModeVocabulary() rows := make([]helpRow, 0, len(vocab)) for _, e := range vocab { @@ -350,7 +349,9 @@ func writeHelpPermissionModes(b *strings.Builder, th theme.Theme, hk helpKeys, e writeHelpBodyLines(b, th, "The posture half applies to the whole server and is fixed when it starts.", "The session half is only the default for new sessions.", - "Cycling the session mode ("+hk.modeSwitch+") never changes the posture half.", + hk.modeSwitch+" cycles every mode. A mode that raises the posture needs a restart, and auto or yolo a guardrails checker;", + "cycling marks it blocked and holds prompts until you press "+hk.cancel+" to return or move on.", + "A mode below the posture applies its session half; the posture stays.", ) if embedded { writeHelpBodyLines(b, th, diff --git a/cmd/mecatui/ui/keys.go b/cmd/mecatui/ui/keys.go index e7bff3e704..b032f7b6a8 100644 --- a/cmd/mecatui/ui/keys.go +++ b/cmd/mecatui/ui/keys.go @@ -63,8 +63,9 @@ type keyMap struct { ScrollTop key.Binding ScrollBottom key.Binding - // ModeSwitch (shift+tab) cycles the session permission mode: default → plan → - // accept-edits → default. Unlike Alt+M, Shift+Tab does not depend on a terminal + // ModeSwitch (shift+tab) cycles every permission mode: default → plan → + // accept-edits → trusted → trusted-accept-edits → auto → yolo → default (see + // cycleMode for modes that need a restart). Unlike Alt+M, Shift+Tab does not depend on a terminal // mapping macOS Option to Meta, and it never collides with prose input. ModeSwitch key.Binding diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go new file mode 100644 index 0000000000..5e543337e2 --- /dev/null +++ b/cmd/mecatui/ui/mode_cycle.go @@ -0,0 +1,221 @@ +package ui + +import ( + "strings" + + "charm.land/bubbles/v2/key" + tea "charm.land/bubbletea/v2" + "charm.land/lipgloss/v2" +) + +// modeCycleOrder is the ModeSwitch order over every permission mode: the +// vocabulary with default and plan swapped, keeping the established +// default → plan → accept-edits start before the posture-raising modes. +func modeCycleOrder() []string { + vocab := PermissionModeVocabulary() + names := make([]string, len(vocab)) + for i, e := range vocab { + names[i] = e.Name + } + names[0], names[1] = names[1], names[0] + return names +} + +// modeCursor is the permission mode the cycle last landed on, valid only while +// the session's desired mode is still the one it recorded. Any other mode change +// (server read-back, new session) invalidates it, so the cycle re-derives its +// position from the live session. +type modeCursor struct { + token string + session string +} + +// postureRank orders the posture tiers. An unknown posture (an older server +// omits it) ranks as strict. +func postureRank(p string) int { + switch p { + case postureTrusted: + return 1 + case postureAuto: + return 2 + case postureYolo: + return 3 + default: + return 0 + } +} + +func permissionModeEntry(name string) PermissionModeEntry { + for _, e := range PermissionModeVocabulary() { + if e.Name == name { + return e + } + } + return PermissionModeEntry{} +} + +// currentModeToken is the cycle position: the mode the cycle last landed on, or +// the mode matching the running posture and the session's desired mode. +func (m Model) currentModeToken() string { + if m.modeCursor.token != "" && m.modeCursor.session == m.desiredMode() { + return m.modeCursor.token + } + return m.acceptedModeToken() +} + +// acceptedModeToken is the mode the session is actually running: the one +// matching the running posture and the session's desired mode, else the +// session mode itself. +func (m Model) acceptedModeToken() string { + session := m.desiredMode() + for _, e := range PermissionModeVocabulary() { + if e.Posture == m.caps.Posture && e.SessionMode == session { + return e.Name + } + } + return session +} + +func nextModeToken(cur string) string { + order := modeCycleOrder() + for i, name := range order { + if name == cur { + return order[(i+1)%len(order)] + } + } + // No position yet (the server default is still unknown): start after default. + return order[1] +} + +// cycleMode lands on the next permission mode. A mode whose posture is at or +// below the running one applies its session half live; one that would raise the +// posture cannot, because the posture is fixed when the server starts, so the +// cycle stops on it and says what to configure and restart. +func (m Model) cycleMode() (tea.Model, tea.Cmd) { + next := permissionModeEntry(nextModeToken(m.currentModeToken())) + if postureRank(next.Posture) > postureRank(m.caps.Posture) { + m.modeCursor = modeCursor{token: next.Name, session: m.desiredMode()} + m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeBlockedStatus()) + (&m).relayout() + return m, nil + } + mm, cmd := m.switchMode(next) + m = mm.(Model) + m.modeCursor = modeCursor{token: next.Name, session: m.desiredMode()} + (&m).relayout() + return m, cmd +} + +// headerMode is the session mode the header shows: the mode the cycle landed +// on when it did, else the session's mode, marked blocked or pending. +func (m Model) headerMode() string { + mode := m.activeMode + if mode == "" { + mode = m.deps.Mode + } + if m.pendingMode != "" { + mode = m.pendingMode + } + if m.modeCursor.token != "" && m.modeCursor.session == m.desiredMode() { + mode = m.modeCursor.token + } + switch { + case m.modeBlocked(): + mode += modeBlockedSuffix + case m.pendingMode != "": + mode += " pending" + } + return mode +} + +// modeBlocked reports that the cycle sits on a mode that needs a restart. The +// session keeps running its accepted mode, but prompts and edits are held so +// nothing is sent under a mode the operator did not mean. +func (m Model) modeBlocked() bool { + e := permissionModeEntry(m.currentModeToken()) + return e.Name != "" && postureRank(e.Posture) > postureRank(m.caps.Posture) +} + +func (m Model) modeEscapeHint() string { + return firstKey(m.keys.Cancel, "esc") + " back to " + m.acceptedModeToken() + " · " + + firstKey(m.keys.ModeSwitch, "shift+tab") + " next mode" +} + +func (m Model) modeBlockedStatus() string { + return "mode " + m.currentModeToken() + " is blocked — " + m.modeEscapeHint() +} + +// leaveBlockedMode is the escape hatch: drop the cursor so the session's +// accepted mode is the current one again. +func (m Model) leaveBlockedMode() Model { + m.modeCursor = modeCursor{} + m.statusMsg = m.deps.Theme.Style("success").Render("mode " + m.acceptedModeToken()) + (&m).relayout() + return m +} + +// onModeBlockedKey holds the prompt while the cycle sits on a blocked mode. Esc +// returns to the accepted mode; the mode switch, scrolling, help, and (at idle) +// the read-only panels still work; every key that would edit or send the draft +// is swallowed with a reminder. The draft itself is kept untouched. +func (m Model) onModeBlockedKey(msg tea.KeyPressMsg) (Model, bool) { + if !m.modeBlocked() || (m.phase != phaseIdle && m.phase != phaseRunning) { + return m, false + } + switch { + case key.Matches(msg, m.keys.Cancel): + return m.leaveBlockedMode(), true + case key.Matches(msg, m.keys.Help): + opened, _ := m.runHelp() + return opened.(Model), true + case key.Matches(msg, m.keys.ModeSwitch), key.Matches(msg, m.keys.CopySelection), + key.Matches(msg, m.keys.ScrollU), key.Matches(msg, m.keys.ScrollD), + key.Matches(msg, m.keys.ScrollTop), key.Matches(msg, m.keys.ScrollBottom): + return m, false + case m.phase == phaseIdle && (key.Matches(msg, m.keys.Agents) || key.Matches(msg, m.keys.MCPPanel) || + key.Matches(msg, m.keys.Resources) || key.Matches(msg, m.keys.Prompts) || key.Matches(msg, m.keys.Effort)): + return m, false + } + m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeBlockedStatus()) + return m, true +} + +// renderModeBlocked replaces the prompt while the mode is blocked: why the mode +// cannot apply, what makes it apply, and how to get back. +func (m Model) renderModeBlocked() string { + th := m.deps.Theme + style := inputRailStyle(th, m.inputMode()) + contentW := max(1, m.width-style.GetHorizontalFrameSize()) + wrap := lipgloss.NewStyle().Width(contentW).Background(th.Color("bgPanel")) + lines := []string{ + wrap.Inherit(th.Style("warning")).Bold(true).Render("⚠ mode " + m.currentModeToken() + " is blocked: prompts and edits are paused, your draft is kept"), + wrap.Inherit(th.Style("text")).Render(m.modeRestartHint(permissionModeEntry(m.currentModeToken()))), + wrap.Inherit(th.Style("muted")).Render(m.modeEscapeHint()), + } + return style.Render(strings.Join(lines, "\n")) +} + +// modeLabel names a landed mode for the footer. A mode below the running +// posture applies only its session half, so the label says the posture stays. +func (m Model) modeLabel(e PermissionModeEntry) string { + if postureRank(e.Posture) < postureRank(m.caps.Posture) { + return e.Name + " · posture " + m.caps.Posture + " stays until restart" + } + return e.Name +} + +// modeRestartHint says why a mode cannot apply now and what makes it apply. +func (m Model) modeRestartHint(e PermissionModeEntry) string { + checker := postureRank(e.Posture) >= postureRank(postureAuto) + if !m.deps.Embedded { + hint := e.Name + " is fixed by the remote server: its operator must restart mecated with --permission-mode " + e.Name + if checker { + hint += " and a guardrails checker" + } + return hint + } + if checker { + return e.Name + " needs a guardrails checker and a restart: set guardrails.model in settings.yaml, then relaunch with mecatui --permission-mode " + e.Name + } + return e.Name + " needs a restart: quit and relaunch with mecatui --permission-mode " + e.Name +} diff --git a/cmd/mecatui/ui/model.go b/cmd/mecatui/ui/model.go index 7169ea625b..dc8200eaba 100644 --- a/cmd/mecatui/ui/model.go +++ b/cmd/mecatui/ui/model.go @@ -822,6 +822,9 @@ type Model struct { // immediate switch. activeMode string pendingMode string + // modeCursor is where the ModeSwitch cycle over every permission mode last + // landed, including a mode that needs a restart and so changed nothing. + modeCursor modeCursor // fullColor is true on a truecolor terminal, derived from the tea.ColorProfileMsg // (msg.Profile == colorprofile.TrueColor) in the reducer. It gates the welcome diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index 9a838ff534..48fc534c0a 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -2,6 +2,7 @@ package ui import ( "context" + "fmt" "strings" "testing" "time" @@ -34,42 +35,221 @@ func statusMode(m Model) string { return m.statusLineInput(time.Now()).Session.Mode } -// cycleMode presses the real ModeSwitch chord and feeds the resulting SetMode -// command back through Update, as the Bubble Tea runtime would. -func cycleMode(t *testing.T, m Model) Model { +// pressModeSwitch presses the real ModeSwitch chord, feeds any resulting SetMode +// command back through Update as the Bubble Tea runtime would, and reports +// whether a command was issued. +func pressModeSwitch(t *testing.T, m Model) (Model, bool) { t.Helper() mm, cmd := m.Update(modeKey()) m = mm.(Model) if cmd == nil { - t.Fatal("mode switch chord issued no SetMode command") + return m, false } - return applyAll(m, cmd()) + return applyAll(m, cmd()), true } -// TestModeSwitchCycleUnchanged pins that the session mode cycle offers -// exactly the three session modes in the same order as before the -// permission-mode vocabulary. No posture-bearing token becomes reachable from -// the keybinding. -func TestModeSwitchCycleUnchanged(t *testing.T) { +// modeCycleStep is one ModeSwitch press: the mode it lands on, whether it +// applies a session half (issues SetMode) or is blocked pending a restart, and +// phrases the footer status or the input area must carry. +type modeCycleStep struct { + token string + setMode bool + blocked bool + status []string +} + +// visibleModeText is the footer status plus the input area, with wrapping and +// the rail border collapsed so a phrase can be matched across a wrapped line. +func visibleModeText(m Model) string { + input := strings.ReplaceAll(stripANSIstr(m.renderInput()), "│", " ") + return strings.Join(strings.Fields(stripANSIstr(m.statusMsg)+" "+input), " ") +} + +func runModeCycle(t *testing.T, m Model, steps []modeCycleStep) Model { + t.Helper() + for i, s := range steps { + var issued bool + m, issued = pressModeSwitch(t, m) + if issued != s.setMode { + t.Fatalf("step %d (%s): SetMode issued = %v, want %v", i, s.token, issued, s.setMode) + } + if got := m.currentModeToken(); got != s.token { + t.Fatalf("step %d: landed on %q, want %q", i, got, s.token) + } + if got := m.modeBlocked(); got != s.blocked { + t.Fatalf("step %d (%s): blocked = %v, want %v", i, s.token, got, s.blocked) + } + wantHeader := s.token + if s.blocked { + wantHeader += " blocked" + } + if got := statusMode(m); got != wantHeader { + t.Fatalf("step %d: header mode = %q, want %q", i, got, wantHeader) + } + text := visibleModeText(m) + for _, want := range s.status { + if !strings.Contains(text, want) { + t.Fatalf("step %d (%s): visible text %q missing %q", i, s.token, text, want) + } + } + } + return m +} + +// TestModeSwitchCyclesEveryMode pins that under strict the cycle lands on all +// seven modes. The posture-raising ones change nothing and say what to +// configure and restart; the strict ones apply live. +func TestModeSwitchCyclesEveryMode(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := permissionModeTestModel(t, conv, postureStrict, true) + m = runModeCycle(t, m, []modeCycleStep{ + {token: "plan", setMode: true, status: []string{"mode plan"}}, + {token: "accept-edits", setMode: true, status: []string{"mode accept-edits"}}, + {token: "trusted", blocked: true, status: []string{"trusted needs a restart", "mecatui --permission-mode trusted", "esc back to accept-edits"}}, + {token: "trusted-accept-edits", blocked: true, status: []string{"mecatui --permission-mode trusted-accept-edits"}}, + {token: "auto", blocked: true, status: []string{"guardrails checker", "guardrails.model", "mecatui --permission-mode auto", "prompts and edits are paused"}}, + {token: "yolo", blocked: true, status: []string{"guardrails checker", "mecatui --permission-mode yolo"}}, + {token: "default", setMode: true, status: []string{"mode default"}}, + {token: "plan", setMode: true}, + }) want := []string{"plan", "accept-edits", "default", "plan"} - for range want { - m = cycleMode(t, m) - } - got := conv.setModes() - if strings.Join(got, ",") != strings.Join(want, ",") { - t.Fatalf("SetMode cycle = %v, want %v", got, want) + if got := conv.setModes(); strings.Join(got, ",") != strings.Join(want, ",") { + t.Fatalf("SetMode calls = %v, want %v", got, want) } if m.activeMode != "plan" { t.Fatalf("active mode after cycle = %q, want plan", m.activeMode) } } +// TestModeSwitchUnderTrustedPosture pins that modes matching the running +// posture apply fully, a mode below it applies its session half and says the +// posture stays, and a mode above it needs a restart. +func TestModeSwitchUnderTrustedPosture(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := permissionModeTestModel(t, conv, postureTrusted, true) + if got := m.currentModeToken(); got != "trusted" { + t.Fatalf("start position = %q, want trusted", got) + } + runModeCycle(t, m, []modeCycleStep{ + {token: "trusted-accept-edits", setMode: true, status: []string{"mode trusted-accept-edits"}}, + {token: "auto", blocked: true, status: []string{"auto needs a guardrails checker", "esc back to trusted-accept-edits"}}, + {token: "yolo", blocked: true, status: []string{"yolo needs a guardrails checker"}}, + {token: "default", setMode: true, status: []string{"mode default · posture trusted stays until restart"}}, + {token: "plan", setMode: true}, + {token: "accept-edits", setMode: true}, + {token: "trusted", setMode: true, status: []string{"mode trusted"}}, + }) + want := []string{"accept-edits", "default", "plan", "accept-edits", "default"} + if got := conv.setModes(); strings.Join(got, ",") != strings.Join(want, ",") { + t.Fatalf("SetMode calls = %v, want %v", got, want) + } +} + +// TestModeSwitchConnectNamesServerRestart pins that under `mecatui connect` a +// posture-raising mode points at the remote server's operator, not a relaunch. +func TestModeSwitchConnectNamesServerRestart(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "accept-edits"} + m := permissionModeTestModel(t, conv, postureStrict, false) + m.activeMode = "accept-edits" + m = runModeCycle(t, m, []modeCycleStep{ + {token: "trusted", blocked: true, status: []string{"remote server", "restart mecated with --permission-mode trusted"}}, + {token: "trusted-accept-edits", blocked: true}, + {token: "auto", blocked: true, status: []string{"--permission-mode auto and a guardrails checker"}}, + }) + if text := visibleModeText(m); strings.Contains(text, "mecatui --permission-mode") { + t.Fatalf("connect hint offers a local relaunch: %q", text) + } + if got := conv.setModes(); len(got) != 0 { + t.Fatalf("SetMode calls = %v, want none", got) + } +} + +// TestBlockedModeHoldsPromptUntilEscape pins that landing on a mode that needs +// a restart holds the prompt: typing, enter, and paste neither edit nor send the +// draft, at idle or mid-run, and esc returns to the accepted mode with the draft +// intact rather than cancelling the run. +func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { + for _, phase := range []phase{phaseIdle, phaseRunning} { + t.Run(fmt.Sprint(phase), func(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := permissionModeTestModel(t, conv, postureStrict, true) + m.prompt.Rewrite("keep this draft") + m = runModeCycle(t, m, []modeCycleStep{ + {token: "plan", setMode: true}, + {token: "accept-edits", setMode: true}, + {token: "trusted", blocked: true}, + }) + m.phase = phaseRunning + if phase == phaseIdle { + m.phase = phaseIdle + } + for _, msg := range []tea.Msg{ + tea.KeyPressMsg{Code: 'x', Text: "x"}, + tea.KeyPressMsg{Code: tea.KeyEnter}, + tea.PasteMsg{Content: "pasted"}, + } { + mm, cmd := m.Update(msg) + m = mm.(Model) + if cmd != nil { + t.Fatalf("%T while blocked issued a command", msg) + } + } + if got := m.prompt.Value(); got != "keep this draft" { + t.Fatalf("blocked prompt changed to %q", got) + } + if len(m.queued) != 0 || m.phase != phase { + t.Fatalf("blocked enter queued %v / moved phase to %v", m.queued, m.phase) + } + if text := visibleModeText(m); !strings.Contains(text, "mode trusted is blocked") || strings.Contains(stripANSIstr(m.renderInput()), "keep this draft") { + t.Fatalf("blocked input area = %q", text) + } + + mm, cmd := m.Update(tea.KeyPressMsg{Code: tea.KeyEscape}) + m = mm.(Model) + if cmd != nil || strings.Contains(stripANSIstr(m.statusMsg), "cancelling") { + t.Fatalf("esc while blocked must only leave the mode, status %q", stripANSIstr(m.statusMsg)) + } + if m.modeBlocked() || statusMode(m) != "accept-edits" { + t.Fatalf("after esc: blocked=%v header=%q, want accept-edits", m.modeBlocked(), statusMode(m)) + } + if !strings.Contains(stripANSIstr(m.renderInput()), "keep this draft") { + t.Fatal("draft not shown again after esc") + } + m = applyAll(m, tea.KeyPressMsg{Code: '!', Text: "!"}) + if got := m.prompt.Value(); got != "keep this draft!" { + t.Fatalf("prompt after esc = %q, want editable again", got) + } + if got := conv.setModes(); strings.Join(got, ",") != "plan,accept-edits" { + t.Fatalf("SetMode calls = %v, want only the two applied modes", got) + } + }) + } +} + +// TestBlockedModeHoldsQueuedPrompt pins that a run ending while the mode is +// blocked does not auto-send the queued follow-up. +func TestBlockedModeHoldsQueuedPrompt(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := permissionModeTestModel(t, conv, postureTrusted, true) + m = runModeCycle(t, m, []modeCycleStep{ + {token: "trusted-accept-edits", setMode: true}, + {token: "auto", blocked: true}, + }) + m.queued = []string{"queued follow-up"} + mm, cmd := m.drainQueue("end_turn") + m = mm.(Model) + if cmd != nil || m.queuePaused != "mode" { + t.Fatalf("drain while blocked: cmd=%v paused=%q, want held", cmd != nil, m.queuePaused) + } + if got := m.prompt.Value(); got != "/queue queued follow-up" { + t.Fatalf("held queue text = %q", got) + } +} + // TestHelpOverlayShowsVocabularyAndScopeSplit pins that every token is // listed with its posture half marked process-wide and its session half marked as // the new-session default, with the exact invocation and the statement that -// cycling the session mode never changes the posture half. +// cycling reaches every mode but a posture-raising one needs a restart. func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := permissionModeTestModel(t, conv, postureStrict, true) @@ -103,7 +283,7 @@ func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { "--permission-mode", "The posture half applies to the whole server and is fixed when it starts.", "The session half is only the default for new sessions.", - "Cycling the session mode (" + m.helpKeyMarkings().modeSwitch + ") never changes the posture half.", + m.helpKeyMarkings().modeSwitch + " cycles every mode. A mode that raises the posture needs a restart", "mecatui --permission-mode ", } { if !strings.Contains(body, phrase) { @@ -148,8 +328,9 @@ func TestHeaderShowsPostureWhenAboveStrict(t *testing.T) { } // TestHeaderKeepsPostureAcrossModeCycle pins that under auto, cycling -// the session mode through plan and back to default keeps the auto badge on every -// frame, including the pending frame before the server confirms each switch. +// through yolo (which needs a restart), default, plan, and accept-edits keeps the +// auto badge on every frame, including the pending frame before the server +// confirms each switch. func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := permissionModeTestModel(t, conv, postureAuto, true) @@ -164,7 +345,17 @@ func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { } } assertAuto("start", "default") - for _, next := range []string{"plan", "accept-edits", "default"} { + // yolo needs a restart, and default is the session half auto already runs: + // neither press needs a server round trip. + for _, step := range []struct{ token, header string }{{"yolo", "yolo blocked"}, {"default", "default"}} { + mm, cmd := m.Update(modeKey()) + m = mm.(Model) + if cmd != nil { + t.Fatalf("landing on %s issued a command", step.token) + } + assertAuto("landed "+step.token, step.header) + } + for _, next := range []string{"plan", "accept-edits"} { mm, cmd := m.Update(modeKey()) m = mm.(Model) if cmd == nil { diff --git a/cmd/mecatui/ui/statusline_source.go b/cmd/mecatui/ui/statusline_source.go index 3295297689..290cc81af1 100644 --- a/cmd/mecatui/ui/statusline_source.go +++ b/cmd/mecatui/ui/statusline_source.go @@ -184,13 +184,7 @@ func (m Model) statusLineInput(now time.Time) customization.Input { workspace.Path = m.statusContextRoot } state, activity, approval := "idle", "", "none" - mode := m.activeMode - if mode == "" { - mode = m.deps.Mode - } - if m.pendingMode != "" { - mode = m.pendingMode + " pending" - } + mode := m.headerMode() handle := client.SessionHandle(m.sessionID) switch m.phase { case phaseConnecting: diff --git a/cmd/mecatui/ui/testdata/help_all_on.golden b/cmd/mecatui/ui/testdata/help_all_on.golden index 7f676681ae..07b366ba31 100644 --- a/cmd/mecatui/ui/testdata/help_all_on.golden +++ b/cmd/mecatui/ui/testdata/help_all_on.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 89 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 91 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/testdata/help_embedded.golden b/cmd/mecatui/ui/testdata/help_embedded.golden index 1a237359e3..610300e438 100644 --- a/cmd/mecatui/ui/testdata/help_embedded.golden +++ b/cmd/mecatui/ui/testdata/help_embedded.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 88 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 90 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/update.go b/cmd/mecatui/ui/update.go index 91dc3426b6..91f15fd0df 100644 --- a/cmd/mecatui/ui/update.go +++ b/cmd/mecatui/ui/update.go @@ -2303,6 +2303,12 @@ func (m Model) onKey(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { return mm, nil } + // A blocked permission mode holds the prompt before paste or any phase key + // can edit or send it. + if mm, handled := m.onModeBlockedKey(msg); handled { + return mm, nil + } + // ctrl+v reads the OS clipboard into the prompt (image → staged attachment, // text → inserted). It is handled here — before the phase switch — for the two // input-accepting phases (idle + running, both keep the textarea focused for @@ -2317,7 +2323,7 @@ func (m Model) onKey(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { // for idle + running so the key never feeds the textarea. It also avoids relying // on macOS Option being configured as Meta. if m.deps.DebugTarget == "" && key.Matches(msg, m.keys.ModeSwitch) && (m.phase == phaseIdle || m.phase == phaseRunning) { - return m.switchMode(client.NextMode(m.desiredMode())) + return m.cycleMode() } return m.dispatchPhaseKey(msg) @@ -2668,18 +2674,21 @@ func createdSessionMode(deps Deps, id, requested string) string { return snap.Mode } -func (m Model) switchMode(mode string) (tea.Model, tea.Cmd) { - mode = client.ModeString(client.ModeFromString(mode)) +// switchMode applies a permission mode's session half to this session. +func (m Model) switchMode(e PermissionModeEntry) (tea.Model, tea.Cmd) { + mode := client.ModeString(client.ModeFromString(e.SessionMode)) if m.sessionID == "" { m.statusMsg = m.deps.Theme.Style("warning").Render("no active session — mode switch unavailable") return m, nil } if mode == m.activeMode && m.pendingMode == "" { - m.statusMsg = m.deps.Theme.Style("muted").Render("mode already " + mode) + // The session is already in this half (e.g. trusted after default under + // a trusted posture): the landing needs no server round trip. + m.statusMsg = m.deps.Theme.Style("success").Render("mode " + m.modeLabel(e)) return m, nil } m.pendingMode = mode - m.statusMsg = m.deps.Theme.Style("muted").Render("switching mode to " + mode + "…") + m.statusMsg = m.deps.Theme.Style("muted").Render("switching mode to " + m.modeLabel(e) + "…") return m, client.SetModeCmd(m.deps.Ctx, m.deps.Session, m.sessionID, mode) } @@ -2702,7 +2711,11 @@ func (m Model) onModeChanged(msg client.ModeChangedMsg) tea.Model { } m.activeMode = mode m.pendingMode = "" - m.statusMsg = m.deps.Theme.Style("success").Render("mode " + mode) + label := mode + if m.modeCursor.session == mode { + label = m.modeLabel(permissionModeEntry(m.modeCursor.token)) + } + m.statusMsg = m.deps.Theme.Style("success").Render("mode " + label) return m } @@ -2969,7 +2982,7 @@ func normalizePastedNewlines(content string) string { // primary-selection paste trigger (onMousePress), so the two paths can never // drift apart. func (m Model) pasteGateOpen() bool { - if m.phase == phaseAwaitingApproval || + if m.phase == phaseAwaitingApproval || m.modeBlocked() || m.modal != nil || m.team.view != teamNone || m.agentsInv.view != agentsInvNone { return false } @@ -4974,6 +4987,11 @@ func (m Model) popAndSubmit() (tea.Model, tea.Cmd) { m.pendingPromptMedia = m.queuedMedia m.queuedMedia = client.MediaResult{} m.prompt.Rewrite("/queue " + merged) + if m.modeBlocked() { + m.statusMsg = m.deps.Theme.Style("warning").Render("queued prompt held: " + m.modeBlockedStatus()) + m.queuePaused = "mode" + return m, nil + } if m.pendingMode != "" { submit := firstKey(m.keys.Submit, "enter") m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + m.pendingMode + " will apply before the queued prompt — press " + submit + " to continue") diff --git a/cmd/mecatui/ui/view.go b/cmd/mecatui/ui/view.go index 7c37d949fb..76519e6495 100644 --- a/cmd/mecatui/ui/view.go +++ b/cmd/mecatui/ui/view.go @@ -274,12 +274,22 @@ func (m Model) headerModelLabel() string { return terminaltext.Sanitize(m.deps.Model) } +// modeBlockedSuffix marks a mode the cycle landed on that needs a restart, in the +// header's session mode and the input rail's mode key. +const modeBlockedSuffix = " blocked" + func (m Model) inputMode() string { + if m.modeBlocked() { + return m.currentModeToken() + modeBlockedSuffix + } return client.ModeString(client.ModeFromString(m.desiredMode())) } func modeAccentStyle(th theme.Theme, mode string) lipgloss.Style { s := lipgloss.NewStyle().Bold(true) + if strings.HasSuffix(mode, modeBlockedSuffix) { + return s.Foreground(th.Color("warning")) + } mode = client.ModeString(client.ModeFromString(strings.TrimSuffix(mode, " pending"))) switch mode { case "plan": @@ -661,6 +671,9 @@ func (m Model) renderPendingPrompt(status string, texts []string, hints string) // chrome()), so the cache is re-keyed in the same step the mutation lands — there // is no window in which a hidden-state change can hide behind an unchanged key. func (m Model) renderInput() string { + if m.modeBlocked() { + return m.renderModeBlocked() + } m.applyModeInputStyle() li := m.prompt.LineInfo() hasSelection := m.prompt.HasSelection() diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index 0469989eac..ee0c011fbb 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -110,24 +110,37 @@ change it for its own session. ### Change the mode after launch -In `mecatui`, press `shift+tab` to cycle the active session through **default → -plan → accept-edits → default**. You can remap the `ModeSwitch` action in the -client keymap or with `--keymap`; see [Keybindings](/mecatui/keybindings.md). - -Cycling changes only the session mode, never the posture. If you start in -`auto` and cycle to `plan` and back to `default`, every tool is still allowed -without asking. The `mecatui` header shows the session mode and, whenever the -posture is above `strict`, the posture as well (`trusted`, `auto`, or `yolo`). - -`mecatui` has no control that selects `trusted`, `trusted-accept-edits`, -`auto`, or `yolo` at runtime. Those modes set the posture, so they need a -restart of the process that hosts the server: +In `mecatui`, press `shift+tab` to cycle through every mode: **default → plan → +accept-edits → trusted → trusted-accept-edits → auto → yolo → default**. You +can remap the `ModeSwitch` action in the client keymap or with `--keymap`; see +[Keybindings](/mecatui/keybindings.md). + +What happens when the cycle lands on a mode depends on the posture the server +is running: + +- **Same posture.** The mode applies immediately. Under `trusted`, landing on + `trusted-accept-edits` switches the session to `accept-edits`. +- **Lower posture.** The session mode applies, but the posture stays until a + restart. If you start in `auto` and cycle to `plan`, every tool is still + allowed without asking, and the footer says so. +- **Higher posture.** The mode is blocked, because the posture is fixed when + the server starts. The header shows it as, for example, `mode auto blocked`. + The prompt area says what the mode needs: a restart, and for `auto` and + `yolo` also a guardrails checker, such as `guardrails.model` in your + user-global `settings.yaml`. While a mode is blocked you can't type, send, + or paste, and queued prompts are held. Your draft is kept. Press `esc` to go + back to the mode the session is running, or `shift+tab` to move on. + +The restart a posture change needs depends on how you connect: - With the embedded server, quit and relaunch `mecatui` with the new `--permission-mode` value. - Under `mecatui connect`, the server operator changes `mecated`'s configuration and restarts it. Relaunching the client changes nothing. +The `mecatui` header shows the session mode and, whenever the posture is above +`strict`, the posture as well (`trusted`, `auto`, or `yolo`). + Press `?` in `mecatui` to see every mode, the two things each one sets, and the restart that applies to your connection. diff --git a/user-docs/mecatui/keybindings.md b/user-docs/mecatui/keybindings.md index aff6379589..aa8cda4b05 100644 --- a/user-docs/mecatui/keybindings.md +++ b/user-docs/mecatui/keybindings.md @@ -23,7 +23,7 @@ bindings and dims features that the connected server does not provide. |`esc`|Clear an active selection first. While work is running, cancel directly and preserve the draft, queued follow-ups, and steer. While idle with a paused queue, clear that queue but preserve the draft.| |`ctrl+t`|Open `/toolcalls` for the current session; approval requests use it for details.| |`f9`|Reveal conversation details: reasoning, turn stats, changed files, permanent error details, benign guardrail notices, and individual settled tool-call summaries. Use `ctrl+t` for tool arguments and results.| -|`shift+tab`|Cycle the current session permission mode: **default → plan → accept-edits → default**. In an MCP prompt argument form, it instead moves to the previous required field.| +|`shift+tab`|Cycle every permission mode: **default → plan → accept-edits → trusted → trusted-accept-edits → auto → yolo → default**. A mode that raises the posture needs a restart: it shows as blocked, prompts and edits are held, and `esc` returns to the running mode. In an MCP prompt argument form, it instead moves to the previous required field.| |`ctrl+g`|Select all prompt text.| |`ctrl+y`|Copy the active prompt or visible conversation selection.| |`f6` / `f7` / `f8`|Open Agents / Effort / MCP Prompts.| diff --git a/user-docs/mecatui/using-the-tui.md b/user-docs/mecatui/using-the-tui.md index 7ed3f17c68..a6cc175c02 100644 --- a/user-docs/mecatui/using-the-tui.md +++ b/user-docs/mecatui/using-the-tui.md @@ -236,9 +236,11 @@ for delegation behavior and the information available in `mecatui`. ## Change conversation settings -Press `shift+tab` to cycle the session through `default`, `plan`, and -`accept-edits`. The modes that change the server's posture, such as `auto`, are -set at launch with `--permission-mode`. See +Press `shift+tab` to cycle through every permission mode. `default`, `plan`, +and `accept-edits` apply immediately. A mode that raises the server's posture, +such as `auto`, needs a restart. The cycle marks it blocked, holds prompts and +edits, and says what to configure and how to relaunch. Press `esc` to return +to the mode the session is running. See [Change the mode after launch](/features/security-and-execution/permissions-and-posture.md#change-the-mode-after-launch). |Command|Result| From 95d36f153d0634c7ebcb3157d855fe3b9fefca21 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 9 Oct 2026 15:17:30 +0300 Subject: [PATCH 16/48] test(permissions): declare the checker choice at allow-all sites added on main Alias-target, subagent-selector, and team-router composition tests added on main build with AllowAllTools but no guardrails decision, which the permission-mode contract now refuses. Declare --guardrails off at those sites. Co-authored-by: Mecatl --- internal/app/subagent_selector_build_test.go | 7 ++++--- internal/app/team_parallel_router_test.go | 1 + internal/app/universal_alias_targets_test.go | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/app/subagent_selector_build_test.go b/internal/app/subagent_selector_build_test.go index 236ecf3fb4..c045b3106b 100644 --- a/internal/app/subagent_selector_build_test.go +++ b/internal/app/subagent_selector_build_test.go @@ -28,9 +28,10 @@ func TestBuildWritableSubagentCrossProviderSelection(t *testing.T) { childReq []port.LLMRequest ) built, err := buildIsolated(t, ctx, Config{ - Workspace: workspace, - NoSoul: true, - AllowAllTools: true, + Workspace: workspace, + NoSoul: true, + AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{ "OPENAI_API_KEY": "sk-test", "OPENROUTER_API_KEY": "sk-test", diff --git a/internal/app/team_parallel_router_test.go b/internal/app/team_parallel_router_test.go index 5b83ca853d..3ccc58f6be 100644 --- a/internal/app/team_parallel_router_test.go +++ b/internal/app/team_parallel_router_test.go @@ -358,6 +358,7 @@ func testTeamBareModelSelectorUsesContextualProvider(t *testing.T, noFS bool, se ModelAliasTargets: ModelAliases{childDefault: {ProviderID: childProvider, Model: "child-default-model"}, "contextual": {Model: selectedModel}}, EnableTeams: true, AllowAllTools: true, + GuardrailsDisabled: true, ContextWindowOverride: 128000, envDetector: fakeEnv(map[string]string{ "OPENAI_API_KEY": "test-key", diff --git a/internal/app/universal_alias_targets_test.go b/internal/app/universal_alias_targets_test.go index ee6cb2c00a..6808a4c781 100644 --- a/internal/app/universal_alias_targets_test.go +++ b/internal/app/universal_alias_targets_test.go @@ -167,6 +167,7 @@ func TestADR_0369_Scenario1_UniversalAliasTargets(t *testing.T) { ModelAliasTargets: cfg.ModelAliasTargets, EnableParallel: true, AllowAllTools: true, + GuardrailsDisabled: true, ContextWindowOverride: 128000, envDetector: fakeEnv(map[string]string{ "OPENAI_API_KEY": "test-key", @@ -308,6 +309,7 @@ func TestADR_0369_Scenario1_SettingsScalarRouterUsesDefaultProvider(t *testing.T NoSoul: true, PermissionConfigs: []string{settings}, AllowAllTools: true, + GuardrailsDisabled: true, ContextWindowOverride: 128000, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "test-key", "OPENROUTER_API_KEY": "test-key"}), liveModelHTTPClient: offlineHTTPClient(), @@ -372,6 +374,7 @@ func TestADR_0369_Scenario1_NamedAutomaticRouterPairAliasTarget(t *testing.T) { RouterCategories: []permconfig.RouterCategory{{Name: "deep", Description: "deep specialist work", Model: "pair-route"}}, RouterDefaultCategory: "deep", AllowAllTools: true, + GuardrailsDisabled: true, envDetector: fakeEnv(map[string]string{"OPENAI_API_KEY": "test-key", "OPENROUTER_API_KEY": "test-key"}), liveModelHTTPClient: offlineHTTPClient(), providerConstructor: func(_ Config, id, _, _ string) port.LLMProvider { From 87dd6835a877763ec0ec38f31c162cac63f2540d Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Wed, 14 Oct 2026 13:03:29 +0300 Subject: [PATCH 17/48] test(permissions): adapt tests added on main to the permission-mode contract TestEmbeddedGuardrailsAdvisoryWarning's no-checker yolo case and the TestBuildSkillFiles* allow-all builds now declare the guardrails kill switch, the explicit choice an allow-all posture requires. TestStartupCompatibilityFreshAccepted expects the GetSession read-back that reports a server-default session's mode. Co-authored-by: Mecatl --- cmd/mecatui/main_test.go | 4 +++- cmd/mecatui/startup_compatibility_test.go | 2 +- internal/app/skill_files_composition_test.go | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/mecatui/main_test.go b/cmd/mecatui/main_test.go index 22a66a1008..af45910d04 100644 --- a/cmd/mecatui/main_test.go +++ b/cmd/mecatui/main_test.go @@ -114,8 +114,10 @@ func TestEmbeddedGuardrailsAdvisoryWarning(t *testing.T) { wantFact: "guardrails: OFF", }, { + // yolo with no checker refuses to start unless the kill switch declares + // the choice; with it, no checker runs and nothing is advisory. name: "no checker yolo from operator settings", - settings: "execution:\n default_placement: host-local\nposture: yolo\n", + settings: "execution:\n default_placement: host-local\nposture: yolo\nguardrails:\n disabled: true\n", wantFact: "guardrails: OFF", }, { diff --git a/cmd/mecatui/startup_compatibility_test.go b/cmd/mecatui/startup_compatibility_test.go index b1444614aa..9a13b8a641 100644 --- a/cmd/mecatui/startup_compatibility_test.go +++ b/cmd/mecatui/startup_compatibility_test.go @@ -189,7 +189,7 @@ func TestStartupCompatibilityFreshAccepted(t *testing.T) { if err != nil || !ran { t.Fatalf("startup error = %v, normal UI ran = %v", err, ran) } - if calls := service.observedCalls(); !reflect.DeepEqual(calls, []string{"GetCompatibilityInfo", "ListModels", "GetCompatibilityInfo", "CreateSession"}) { + if calls := service.observedCalls(); !reflect.DeepEqual(calls, []string{"GetCompatibilityInfo", "ListModels", "GetCompatibilityInfo", "CreateSession", "GetSession"}) { t.Fatalf("fresh startup RPCs = %v", calls) } } diff --git a/internal/app/skill_files_composition_test.go b/internal/app/skill_files_composition_test.go index c9911ca829..6689035473 100644 --- a/internal/app/skill_files_composition_test.go +++ b/internal/app/skill_files_composition_test.go @@ -31,7 +31,7 @@ func TestBuildSkillFilesResolveThroughTheCallersOwnView(t *testing.T) { built, err := Build(context.Background(), Config{ Workspace: t.TempDir(), Model: "mock", StoreDir: t.TempDir(), UserModelDir: userModelDir, - NoSoul: true, OwnershipEnforced: true, AllowAllTools: true, MockProvider: mockllm.New(), + NoSoul: true, OwnershipEnforced: true, AllowAllTools: true, GuardrailsDisabled: true, MockProvider: mockllm.New(), }) if err != nil { t.Fatal(err) @@ -85,7 +85,7 @@ func TestBuildSkillFilesWithoutALearnedSkillStore(t *testing.T) { t.Setenv("XDG_DATA_HOME", "") built, err := Build(context.Background(), Config{ Workspace: t.TempDir(), Model: "mock", StoreDir: t.TempDir(), UserModelDir: userModelDir, - NoSoul: true, AllowAllTools: true, MockProvider: mockllm.New(), SkillsDirs: []string{skills}, + NoSoul: true, AllowAllTools: true, GuardrailsDisabled: true, MockProvider: mockllm.New(), SkillsDirs: []string{skills}, }) if err != nil { t.Fatal(err) From a520baac1049ea1d27f99056e43916a881d552c7 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Wed, 14 Oct 2026 19:55:37 +0300 Subject: [PATCH 18/48] refactor(permissions): make allow-all and loose-substitution mode-driven Replace the startup-time posture-derived allow-all injection with session-mode-driven evaluation. Policy.Evaluate now injects allowAllCLIRules() for ModeAuto and ModeYolo and selects an evalLoose evaluator for ModeYolo, so switching a session from yolo to default actually removes the allow-all floor instead of only flipping a label. Engine changes: - Add ModeAuto and ModeYolo to session.PermissionMode (5 modes total) - Policy holds eval and evalLoose evaluators; Evaluate switches on mode - allowAllCLIRules() at ScopeCLI is injected as extras, not baked into the static ruleset at startup Composition changes: - mainRules/childRules no longer inject the allow-all rule - mainEvaluatorOptions/childEvaluatorOptions no longer pass WithLooseSubstitution (mode drives it via evalLoose) - applyPosture no longer sets AllowAllTools or LooseChildSubstitution; TrustProject floor logic is unchanged - Config gains MaxAllowedMode; SetMode in service.go enforces the server ceiling and gates ModeAuto entry on checker availability - checkerRefusal becomes a startup WARN (not an error); the hard gate is now SetMode at runtime Token vocabulary reduced from 7 to 5: - Drop trusted and trusted-accept-edits; trust is --trust-project only - auto sessions start in ModeAuto; yolo sessions start in ModeYolo - Deprecated --posture aliases map to equivalent session modes via postureToSessionModes Wire: add PERMISSION_MODE_AUTO=4 and PERMISSION_MODE_YOLO=5 to the proto enum (additive, non-breaking); regenerate contracts/gen. Co-authored-by: Mecatl --- cmd/mecak8s/permission_mode.go | 25 +- cmd/mecak8s/permission_mode_test.go | 77 +- cmd/mecated/permission_mode.go | 12 +- cmd/mecated/permission_mode_test.go | 46 +- cmd/mecatequi/permission_mode.go | 24 +- cmd/mecatequi/permission_mode_test.go | 2 +- cmd/mecatui/permission_mode.go | 24 +- cmd/mecatui/permission_mode_test.go | 6 +- cmd/mecatui/ui/help.go | 5 +- .../ui/permission_mode_vocabulary_test.go | 46 +- cmd/mecatui/ui/testdata/help_all_on.golden | 2 +- cmd/mecatui/ui/testdata/help_embedded.golden | 2 +- contracts/gen/go/mecatl/v1/harness.pb.go | 1176 +++++++++-------- contracts/proto/mecatl/v1/harness.proto | 13 +- engine/adapter/permpolicy/permpolicy.go | 84 +- engine/session/session.go | 10 + internal/adapter/server/service.go | 49 + internal/app/allowall_test.go | 392 +++--- internal/app/authority_vertical_test.go | 8 +- internal/app/build.go | 173 +-- .../app/contextual_build_evidence_test.go | 5 +- ...contextual_guardrails_task5_prompt_test.go | 15 +- internal/app/contextual_new_write_test.go | 3 +- internal/app/contextual_repair2b_test.go | 3 +- .../app/guardrails_approve_once_e2e_test.go | 12 +- .../app/harness_context_authority_test.go | 6 +- .../harness_context_execution_source_test.go | 8 +- .../app/harness_context_execution_test.go | 5 +- .../app/harness_context_generation_test.go | 2 +- internal/app/harness_context_hybrid_test.go | 3 +- .../app/harness_context_principal_test.go | 3 +- .../app/harness_context_regression_test.go | 3 +- .../app/learned_skills_composition_test.go | 11 +- .../mcp_broker_authorization_vertical_test.go | 2 +- internal/app/microvm_harness_context_test.go | 6 +- internal/app/microvm_lifecycle_e2e_test.go | 14 +- internal/app/multiprovider_e2e_test.go | 22 +- internal/app/openai_codex_composition_test.go | 10 +- internal/app/permission_mode.go | 104 +- internal/app/permission_mode_test.go | 248 ++-- internal/app/posture.go | 59 +- internal/app/posture_build_test.go | 6 +- internal/app/posture_test.go | 68 +- internal/app/remote_execution_test.go | 8 +- internal/app/router_test.go | 6 +- internal/app/scheduler_fire.go | 10 +- ...rver_provider_recovery_composition_test.go | 4 +- internal/app/steer_composition_test.go | 4 +- internal/app/subagent_agent_router_test.go | 6 +- internal/app/subagent_model_default_test.go | 2 +- internal/app/subagent_perm_config_test.go | 25 +- internal/app/subagent_selector_build_test.go | 4 +- .../subagent_writable_agent_router_test.go | 2 +- internal/app/subprovider_test.go | 4 +- internal/app/team_parallel_router_test.go | 10 +- internal/app/universal_alias_targets_test.go | 3 +- .../src/gen/mecatl/v1/harness_pb.ts | 25 +- 57 files changed, 1554 insertions(+), 1353 deletions(-) diff --git a/cmd/mecak8s/permission_mode.go b/cmd/mecak8s/permission_mode.go index c3b79a05ad..3f05766d23 100644 --- a/cmd/mecak8s/permission_mode.go +++ b/cmd/mecak8s/permission_mode.go @@ -14,8 +14,8 @@ import ( // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + - ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; trusted for trusted and trusted-accept-edits; auto; yolo), " + - "and the session mode new sessions start in, which each session may change. Default: auto (posture auto, default session mode). " + + ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; auto; yolo), " + + "and the session mode new sessions start in, which each session may change. Default: auto (posture auto, auto session mode). " + "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model or the guardrail model slot) or an explicit --guardrails off, and require MECATL_SANDBOX when running as root. " + "Deny rules and configured ask rules still apply. Replaces the deprecated --posture; --trust-project still combines with it" @@ -41,11 +41,22 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { if diag == nil || !cfg.postureFlagSet { return } - replacement := "default" - if tok, ok := app.PermissionModeForPair(app.ParsePosture(cfg.posture), session.ModeDefault); ok { - replacement = tok.Name - } diag.Log(context.Background(), port.LevelWarn, "--posture is DEPRECATED; use --permission-mode instead", - "posture", cfg.posture, "replacement", "--permission-mode "+replacement) + "posture", cfg.posture, "replacement", "--permission-mode "+postureReplacementToken(cfg.posture)) +} + +// postureReplacementToken names the token that replaces a legacy --posture value. +// auto and yolo are their own tokens; the strict-posture tiers map to "default". +func postureReplacementToken(raw string) string { + switch app.ParsePosture(raw) { + case app.PostureAuto: + return "auto" + case app.PostureYolo: + return "yolo" + } + if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { + return tok.Name + } + return "default" } diff --git a/cmd/mecak8s/permission_mode_test.go b/cmd/mecak8s/permission_mode_test.go index f610d3a18e..66704e069a 100644 --- a/cmd/mecak8s/permission_mode_test.go +++ b/cmd/mecak8s/permission_mode_test.go @@ -55,14 +55,25 @@ func k8sDeprecationWarnings(t *testing.T, argv ...string) []string { } func TestDeprecatedAliasesStillResolve(t *testing.T) { - for _, tc := range []struct{ posture, token string }{ - {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, + // Each deprecated --posture alias must resolve to the correct posture and emit + // exactly one deprecation WARN naming the replacement --permission-mode token. + // Session mode for deprecated paths is set inside Build (not at flag-parse time). + for _, tc := range []struct { + posture string + wantPosture app.Posture + token string + }{ + {"strict", app.PostureStrict, "default"}, + {"auto", app.PostureAuto, "auto"}, + {"yolo", app.PostureYolo, "yolo"}, } { t.Run(tc.posture, func(t *testing.T) { - aliasPosture, aliasMode, _ := k8sPair(t, "--posture", tc.posture) - tokPosture, tokMode, _ := k8sPair(t, "--permission-mode", tc.token) - if aliasPosture != tokPosture || aliasMode != tokMode { - t.Fatalf("--posture %s = (%s, %s), want the %q token's (%s, %s)", tc.posture, aliasPosture, aliasMode, tc.token, tokPosture, tokMode) + aliasPosture, _, ac := k8sPair(t, "--posture", tc.posture) + if aliasPosture != tc.wantPosture { + t.Fatalf("--posture %s posture = %s, want %s", tc.posture, aliasPosture, tc.wantPosture) + } + if ac.DefaultSessionMode != "" { + t.Fatalf("--posture %s: cmd layer must not set DefaultSessionMode (got %q); Build sets it", tc.posture, ac.DefaultSessionMode) } warns := k8sDeprecationWarnings(t, "--posture", tc.posture) if len(warns) != 1 || !strings.Contains(warns[0], "--permission-mode "+tc.token) { @@ -113,30 +124,44 @@ func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { } func TestBareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { - build := func(argv ...string) error { - cfg, err := parseFlags(argv) - if err != nil { - t.Fatalf("parseFlags(%q): %v", argv, err) - } - ac := appConfig(cfg, port.NopDiagnostics{}, observability{}) - ac.RedisURL = "" - ac.SchedulerEnabled = false - ac.SessionLeaseK8sNamespace = "" - ac.Workspace = t.TempDir() - ac.MockProvider = mockllm.New() - built, err := buildIsolated(t, context.Background(), ac) - if err == nil { - built.Close() - } - return err + // The checker gate is now a startup WARN, not a refusal. + // Build succeeds; entering auto mode without a checker is refused at SetMode time. + var buf bytes.Buffer + diag := slogdiag.NewFromLogger(slog.New(slog.NewTextHandler(&buf, nil))) + cfg, err := parseFlags(nil) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + ac := appConfig(cfg, diag, observability{}) + ac.RedisURL = "" + ac.SchedulerEnabled = false + ac.SessionLeaseK8sNamespace = "" + ac.Workspace = t.TempDir() + ac.MockProvider = mockllm.New() + built, err := buildIsolated(t, context.Background(), ac) + if err != nil { + t.Fatalf("bare mecak8s must start (checker gate is now a WARN): %v", err) } - err := build() - if err == nil || !strings.Contains(err.Error(), "no guardrails checker") || !strings.Contains(err.Error(), "--guardrails off") { - t.Fatalf("bare mecak8s Build err = %v, want the checker refusal naming --guardrails off", err) + built.Close() + if !strings.Contains(buf.String(), "no guardrails checker") || !strings.Contains(buf.String(), "--guardrails off") { + t.Errorf("bare mecak8s must WARN naming --guardrails off; log:\n%s", buf.String()) } - if err := build("--guardrails=off"); err != nil { + // With --guardrails off, Build must still succeed (no checker needed). + cfgOff, err := parseFlags([]string{"--guardrails=off"}) + if err != nil { + t.Fatalf("parseFlags --guardrails=off: %v", err) + } + acOff := appConfig(cfgOff, port.NopDiagnostics{}, observability{}) + acOff.RedisURL = "" + acOff.SchedulerEnabled = false + acOff.SessionLeaseK8sNamespace = "" + acOff.Workspace = t.TempDir() + acOff.MockProvider = mockllm.New() + built2, err := buildIsolated(t, context.Background(), acOff) + if err != nil { t.Fatalf("mecak8s with an explicit --guardrails=off: %v", err) } + built2.Close() } func TestPermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { diff --git a/cmd/mecated/permission_mode.go b/cmd/mecated/permission_mode.go index db3c37c779..a53a40a727 100644 --- a/cmd/mecated/permission_mode.go +++ b/cmd/mecated/permission_mode.go @@ -14,7 +14,7 @@ import ( // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + - ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; trusted for trusted and trusted-accept-edits; auto; yolo), " + + ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; auto; yolo), " + "and the session mode new sessions start in, which each session may change. Default: default. " + "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model) or an explicit --guardrails off, and are refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1. " + "Deny rules and configured ask rules still apply. Replaces the deprecated --posture and --yolo; --trust-project still combines with it." @@ -57,9 +57,15 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { } } -// postureReplacementToken names the token equivalent to a legacy --posture -// value with the default session mode (strict maps to default). +// postureReplacementToken names the token that replaces a legacy --posture value. +// auto and yolo are their own tokens; the strict-posture tiers map to "default". func postureReplacementToken(raw string) string { + switch app.ParsePosture(raw) { + case app.PostureAuto: + return "auto" + case app.PostureYolo: + return "yolo" + } if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { return tok.Name } diff --git a/cmd/mecated/permission_mode_test.go b/cmd/mecated/permission_mode_test.go index 8b500e23af..02af160972 100644 --- a/cmd/mecated/permission_mode_test.go +++ b/cmd/mecated/permission_mode_test.go @@ -57,24 +57,26 @@ func deprecationWarnings(t *testing.T, argv ...string) []string { } func TestDeprecatedAliasesStillResolve(t *testing.T) { + // Each deprecated alias must resolve to the correct posture and emit exactly + // one deprecation WARN naming the replacement --permission-mode token. + // Session mode is set inside Build (via foldPermissionMode), not at flag-parse + // time, so the pre-Build resolvedPair returns ModeDefault for deprecated paths. cases := []struct { - name string - alias []string - token string + name string + alias []string + wantPosture app.Posture + wantToken string }{ - {"posture strict", []string{"--posture", "strict"}, "default"}, - {"posture trusted", []string{"--posture", "trusted"}, "trusted"}, - {"posture auto", []string{"--posture", "auto"}, "auto"}, - {"posture yolo", []string{"--posture", "yolo"}, "yolo"}, - {"yolo", []string{"--yolo"}, "yolo"}, + {"posture strict", []string{"--posture", "strict"}, app.PostureStrict, "default"}, + {"posture auto", []string{"--posture", "auto"}, app.PostureAuto, "auto"}, + {"posture yolo", []string{"--posture", "yolo"}, app.PostureYolo, "yolo"}, + {"yolo", []string{"--yolo"}, app.PostureYolo, "yolo"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - aliasPosture, aliasMode, _ := resolvedPair(t, tc.alias...) - tokPosture, tokMode, _ := resolvedPair(t, "--permission-mode", tc.token) - if aliasPosture != tokPosture || aliasMode != tokMode { - t.Fatalf("%q resolved to (%s, %s), want the %q token's (%s, %s)", - tc.alias, aliasPosture, aliasMode, tc.token, tokPosture, tokMode) + aliasPosture, _, _ := resolvedPair(t, tc.alias...) + if aliasPosture != tc.wantPosture { + t.Fatalf("%q posture = %s, want %s", tc.alias, aliasPosture, tc.wantPosture) } warns := deprecationWarnings(t, tc.alias...) if len(warns) != 1 { @@ -83,8 +85,8 @@ func TestDeprecatedAliasesStillResolve(t *testing.T) { if !strings.Contains(warns[0], "--permission-mode") { t.Fatalf("deprecation WARN does not name --permission-mode: %s", warns[0]) } - if !strings.Contains(warns[0], "--permission-mode "+tc.token) { - t.Fatalf("deprecation WARN does not name the replacement token %q: %s", tc.token, warns[0]) + if !strings.Contains(warns[0], "--permission-mode "+tc.wantToken) { + t.Fatalf("deprecation WARN does not name the replacement token %q: %s", tc.wantToken, warns[0]) } }) } @@ -99,16 +101,18 @@ func TestAliasCombinationsStillResolve(t *testing.T) { name string argv []string wantPosture app.Posture + wantMode session.PermissionMode wantTrust bool wantAllow bool }{ // Interactive root: --trust-project raises an explicit strict to trusted, today's MAX fold. - {"posture strict trust-project interactive", []string{"--posture", "strict", "--trust-project"}, app.PostureTrusted, true, false}, + {"posture strict trust-project interactive", []string{"--posture", "strict", "--trust-project"}, app.PostureTrusted, session.ModeDefault, true, false}, // Headless root: no token grants trust on headless, so yolo plus explicit trust has no single-token spelling. - {"yolo trust-project headless", []string{"--headless", "--yolo", "--trust-project"}, app.PostureYolo, true, true}, - {"posture auto yolo", []string{"--posture", "auto", "--yolo"}, app.PostureYolo, false, true}, + {"yolo trust-project headless", []string{"--headless", "--yolo", "--trust-project"}, app.PostureYolo, session.ModeDefault, true, true}, + {"posture auto yolo", []string{"--posture", "auto", "--yolo"}, app.PostureYolo, session.ModeDefault, false, true}, // --trust-project is not deprecated and still combines with the new flag. - {"permission-mode auto trust-project headless", []string{"--headless", "--permission-mode", "auto", "--trust-project"}, app.PostureAuto, true, false}, + // --permission-mode auto sets session mode to ModeAuto via the token table. + {"permission-mode auto trust-project headless", []string{"--headless", "--permission-mode", "auto", "--trust-project"}, app.PostureAuto, session.ModeAuto, true, false}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -116,8 +120,8 @@ func TestAliasCombinationsStillResolve(t *testing.T) { if posture != tc.wantPosture { t.Fatalf("%q posture = %s, want %s", tc.argv, posture, tc.wantPosture) } - if mode != session.ModeDefault { - t.Fatalf("%q session mode = %s, want default", tc.argv, mode) + if mode != tc.wantMode { + t.Fatalf("%q session mode = %s, want %s", tc.argv, mode, tc.wantMode) } if ac.TrustProject != tc.wantTrust { t.Fatalf("%q TrustProject = %v, want %v", tc.argv, ac.TrustProject, tc.wantTrust) diff --git a/cmd/mecatequi/permission_mode.go b/cmd/mecatequi/permission_mode.go index 847baf00ef..27f96e4d26 100644 --- a/cmd/mecatequi/permission_mode.go +++ b/cmd/mecatequi/permission_mode.go @@ -14,10 +14,9 @@ import ( // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + - ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; trusted for trusted and trusted-accept-edits; auto; yolo), " + + ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; auto; yolo), " + "and the session mode the run's session starts in. Default: default. " + "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model or the guardrail model slot) or an explicit --guardrails off. " + - "trusted and trusted-accept-edits need a trust source such as --trust-project on this headless root. " + "Deny and configured ask rules still apply. Replaces the deprecated --posture; --trust-project still combines with it." // validatePermissionModeFlags fails fast on an unknown --permission-mode token @@ -41,11 +40,22 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, f flags) { if diag == nil || !f.postureFlagSet { return } - replacement := "default" - if tok, ok := app.PermissionModeForPair(app.ParsePosture(f.posture), session.ModeDefault); ok { - replacement = tok.Name - } diag.Log(context.Background(), port.LevelWarn, "--posture is DEPRECATED; use --permission-mode instead", - "posture", f.posture, "replacement", "--permission-mode "+replacement) + "posture", f.posture, "replacement", "--permission-mode "+postureReplacementToken(f.posture)) +} + +// postureReplacementToken names the token that replaces a legacy --posture value. +// auto and yolo are their own tokens; the strict-posture tiers map to "default". +func postureReplacementToken(raw string) string { + switch app.ParsePosture(raw) { + case app.PostureAuto: + return "auto" + case app.PostureYolo: + return "yolo" + } + if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { + return tok.Name + } + return "default" } diff --git a/cmd/mecatequi/permission_mode_test.go b/cmd/mecatequi/permission_mode_test.go index e67984d2a4..e31b64cb1b 100644 --- a/cmd/mecatequi/permission_mode_test.go +++ b/cmd/mecatequi/permission_mode_test.go @@ -21,7 +21,7 @@ import ( func TestDeprecatedAliasesStillResolve(t *testing.T) { for _, tc := range []struct{ posture, token string }{ - {"strict", "default"}, {"trusted", "trusted"}, {"auto", "auto"}, {"yolo", "yolo"}, + {"strict", "default"}, {"auto", "auto"}, {"yolo", "yolo"}, } { t.Run(tc.posture, func(t *testing.T) { alias, err := parseFlags([]string{"--prompt", "x", "--posture", tc.posture}) diff --git a/cmd/mecatui/permission_mode.go b/cmd/mecatui/permission_mode.go index 06ded56990..ea22dfd2c2 100644 --- a/cmd/mecatui/permission_mode.go +++ b/cmd/mecatui/permission_mode.go @@ -114,12 +114,26 @@ func deprecatedPermissionFlagWarnings(c config) []string { } hint := "no single token names this combination; it still resolves as before" posture := app.ResolveAliasPosture(app.ParsePosture(c.posture), c.allowAllTools, c.trustProject) - mode := c.mode if !c.modeFlagSet { - mode = client.ModeDefaultString - } - if tok, ok := app.PermissionModeForPair(posture, sessionModeFromTUI(mode)); ok { - hint = "use --permission-mode " + tok.Name + // No explicit session mode: look up the replacement token by posture alone. + // auto and yolo have their own session modes (ModeAuto/ModeYolo); the + // strict-posture tiers use ModeDefault. PermissionModeForPair with ModeDefault + // would miss auto and yolo since their tokens now use their own modes. + switch posture { + case app.PostureAuto: + hint = "use --permission-mode auto" + case app.PostureYolo: + hint = "use --permission-mode yolo" + default: + if tok, ok := app.PermissionModeForPair(posture, session.ModeDefault); ok { + hint = "use --permission-mode " + tok.Name + } + } + } else { + mode := c.mode + if tok, ok := app.PermissionModeForPair(posture, sessionModeFromTUI(mode)); ok { + hint = "use --permission-mode " + tok.Name + } } var out []string add := func(flagName string) { diff --git a/cmd/mecatui/permission_mode_test.go b/cmd/mecatui/permission_mode_test.go index bf9ae20f9f..3a8e68f1e9 100644 --- a/cmd/mecatui/permission_mode_test.go +++ b/cmd/mecatui/permission_mode_test.go @@ -109,7 +109,7 @@ func TestPermissionModeConflictsWithAliases(t *testing.T) { } } _, _, err := parseTransportFlagsTest(t, modeLocal, []string{"--mock", "--workspace", "/abs", "--permission-mode", "accept-all"}) - if err == nil || !strings.Contains(err.Error(), "trusted-accept-edits") { + if err == nil || !strings.Contains(err.Error(), "accept-edits") { t.Fatalf("unknown token error = %v, want the valid token list", err) } if _, _, err := parseTransportFlagsTest(t, modeLocal, []string{"--mock", "--workspace", "/abs", "--permission-mode", "plan", "--trust-project"}); err != nil { @@ -128,7 +128,7 @@ func TestConnectRefusesPostureHalf(t *testing.T) { if mode, serverDefault := cfg.requestedSessionMode(); mode != "accept-edits" || serverDefault { t.Errorf("connect session half = %q (server default %v), want accept-edits", mode, serverDefault) } - for _, tok := range []string{"trusted", "trusted-accept-edits", "auto", "yolo"} { + for _, tok := range []string{"auto", "yolo"} { _, _, err := parseTransportFlagsTest(t, modeConnect, []string{"--permission-mode", tok}) if err == nil { t.Fatalf("connect --permission-mode %s: want an error", tok) @@ -177,7 +177,7 @@ func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { {name: "unconfigured", args: nil, wantPosture: "strict", wantMode: "default"}, {name: "mode plan", args: []string{"--mode", "plan"}, wantPosture: "strict", wantMode: "plan"}, {name: "permission-mode plan", args: []string{"--permission-mode", "plan"}, wantPosture: "strict", wantMode: "plan"}, - {name: "permission-mode trusted-accept-edits", args: []string{"--permission-mode", "trusted-accept-edits"}, wantPosture: "trusted", wantMode: "accept-edits"}, + {name: "permission-mode accept-edits", args: []string{"--permission-mode", "accept-edits"}, wantPosture: "strict", wantMode: "accept-edits"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 840187b56b..59c16ea676 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -323,12 +323,13 @@ type PermissionModeEntry struct { // cannot import the composition layer, so this is a display copy; a test in the // mecatui main package pins it to app.ParsePermissionMode so the two never drift. func PermissionModeVocabulary() []PermissionModeEntry { + // 5-token vocabulary (trusted and trusted-accept-edits removed; auto and yolo + // now have their own session modes ModeAuto/ModeYolo, which the proto wire and + // TUI render as "default" via ModeString(ModeFromString(...))). return []PermissionModeEntry{ {Name: "plan", Posture: postureStrict, SessionMode: "plan"}, {Name: "default", Posture: postureStrict, SessionMode: client.ModeDefaultString}, {Name: "accept-edits", Posture: postureStrict, SessionMode: "accept-edits"}, - {Name: "trusted", Posture: postureTrusted, SessionMode: client.ModeDefaultString}, - {Name: "trusted-accept-edits", Posture: postureTrusted, SessionMode: "accept-edits"}, {Name: "auto", Posture: postureAuto, SessionMode: client.ModeDefaultString}, {Name: "yolo", Posture: postureYolo, SessionMode: client.ModeDefaultString}, } diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index 48fc534c0a..669db1fc6d 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -97,16 +97,14 @@ func runModeCycle(t *testing.T, m Model, steps []modeCycleStep) Model { } // TestModeSwitchCyclesEveryMode pins that under strict the cycle lands on all -// seven modes. The posture-raising ones change nothing and say what to -// configure and restart; the strict ones apply live. +// five modes. The posture-raising ones (auto, yolo) change nothing and say what +// to configure and restart; the strict ones apply live. func TestModeSwitchCyclesEveryMode(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := permissionModeTestModel(t, conv, postureStrict, true) m = runModeCycle(t, m, []modeCycleStep{ {token: "plan", setMode: true, status: []string{"mode plan"}}, {token: "accept-edits", setMode: true, status: []string{"mode accept-edits"}}, - {token: "trusted", blocked: true, status: []string{"trusted needs a restart", "mecatui --permission-mode trusted", "esc back to accept-edits"}}, - {token: "trusted-accept-edits", blocked: true, status: []string{"mecatui --permission-mode trusted-accept-edits"}}, {token: "auto", blocked: true, status: []string{"guardrails checker", "guardrails.model", "mecatui --permission-mode auto", "prompts and edits are paused"}}, {token: "yolo", blocked: true, status: []string{"guardrails checker", "mecatui --permission-mode yolo"}}, {token: "default", setMode: true, status: []string{"mode default"}}, @@ -121,25 +119,30 @@ func TestModeSwitchCyclesEveryMode(t *testing.T) { } } -// TestModeSwitchUnderTrustedPosture pins that modes matching the running -// posture apply fully, a mode below it applies its session half and says the -// posture stays, and a mode above it needs a restart. +// TestModeSwitchUnderTrustedPosture pins that a server running with the legacy +// trusted posture (reachable via deprecated --posture trusted) handles the +// 5-token vocabulary correctly: strict-posture tokens apply their session half, +// posture-raising tokens (auto, yolo) are blocked. +// Since "trusted" is no longer a named token, the start position is the session +// mode itself ("default"), and cycling visits all five tokens. func TestModeSwitchUnderTrustedPosture(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := permissionModeTestModel(t, conv, postureTrusted, true) - if got := m.currentModeToken(); got != "trusted" { - t.Fatalf("start position = %q, want trusted", got) + // No vocabulary entry for posture=trusted; acceptedModeToken falls back to + // the session mode string. + if got := m.currentModeToken(); got != "default" { + t.Fatalf("start position = %q, want default (no trusted token in vocabulary)", got) } runModeCycle(t, m, []modeCycleStep{ - {token: "trusted-accept-edits", setMode: true, status: []string{"mode trusted-accept-edits"}}, - {token: "auto", blocked: true, status: []string{"auto needs a guardrails checker", "esc back to trusted-accept-edits"}}, + {token: "plan", setMode: true}, + {token: "accept-edits", setMode: true}, + // auto and yolo raise posture above trusted → blocked (need restart). + {token: "auto", blocked: true, status: []string{"auto needs a guardrails checker", "esc back to accept-edits"}}, {token: "yolo", blocked: true, status: []string{"yolo needs a guardrails checker"}}, {token: "default", setMode: true, status: []string{"mode default · posture trusted stays until restart"}}, {token: "plan", setMode: true}, - {token: "accept-edits", setMode: true}, - {token: "trusted", setMode: true, status: []string{"mode trusted"}}, }) - want := []string{"accept-edits", "default", "plan", "accept-edits", "default"} + want := []string{"plan", "accept-edits", "default", "plan"} if got := conv.setModes(); strings.Join(got, ",") != strings.Join(want, ",") { t.Fatalf("SetMode calls = %v, want %v", got, want) } @@ -152,9 +155,8 @@ func TestModeSwitchConnectNamesServerRestart(t *testing.T) { m := permissionModeTestModel(t, conv, postureStrict, false) m.activeMode = "accept-edits" m = runModeCycle(t, m, []modeCycleStep{ - {token: "trusted", blocked: true, status: []string{"remote server", "restart mecated with --permission-mode trusted"}}, - {token: "trusted-accept-edits", blocked: true}, {token: "auto", blocked: true, status: []string{"--permission-mode auto and a guardrails checker"}}, + {token: "yolo", blocked: true, status: []string{"remote server"}}, }) if text := visibleModeText(m); strings.Contains(text, "mecatui --permission-mode") { t.Fatalf("connect hint offers a local relaunch: %q", text) @@ -177,7 +179,7 @@ func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { m = runModeCycle(t, m, []modeCycleStep{ {token: "plan", setMode: true}, {token: "accept-edits", setMode: true}, - {token: "trusted", blocked: true}, + {token: "auto", blocked: true}, }) m.phase = phaseRunning if phase == phaseIdle { @@ -200,7 +202,7 @@ func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { if len(m.queued) != 0 || m.phase != phase { t.Fatalf("blocked enter queued %v / moved phase to %v", m.queued, m.phase) } - if text := visibleModeText(m); !strings.Contains(text, "mode trusted is blocked") || strings.Contains(stripANSIstr(m.renderInput()), "keep this draft") { + if text := visibleModeText(m); !strings.Contains(text, "mode auto is blocked") || strings.Contains(stripANSIstr(m.renderInput()), "keep this draft") { t.Fatalf("blocked input area = %q", text) } @@ -230,9 +232,10 @@ func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { // blocked does not auto-send the queued follow-up. func TestBlockedModeHoldsQueuedPrompt(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := permissionModeTestModel(t, conv, postureTrusted, true) + m := permissionModeTestModel(t, conv, postureStrict, true) m = runModeCycle(t, m, []modeCycleStep{ - {token: "trusted-accept-edits", setMode: true}, + {token: "plan", setMode: true}, + {token: "accept-edits", setMode: true}, {token: "auto", blocked: true}, }) m.queued = []string{"queued follow-up"} @@ -256,12 +259,11 @@ func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { body := stripANSIstr(m.helpBody()) // The token table, written out independently of PermissionModeVocabulary. + // 5-token vocabulary: trusted and trusted-accept-edits removed. want := []struct{ token, posture, session string }{ {"plan", "strict", "plan"}, {"default", "strict", "default"}, {"accept-edits", "strict", "accept-edits"}, - {"trusted", "trusted", "default"}, - {"trusted-accept-edits", "trusted", "accept-edits"}, {"auto", "auto", "default"}, {"yolo", "yolo", "default"}, } diff --git a/cmd/mecatui/ui/testdata/help_all_on.golden b/cmd/mecatui/ui/testdata/help_all_on.golden index 07b366ba31..7f676681ae 100644 --- a/cmd/mecatui/ui/testdata/help_all_on.golden +++ b/cmd/mecatui/ui/testdata/help_all_on.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 91 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 89 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/testdata/help_embedded.golden b/cmd/mecatui/ui/testdata/help_embedded.golden index 610300e438..1a237359e3 100644 --- a/cmd/mecatui/ui/testdata/help_embedded.golden +++ b/cmd/mecatui/ui/testdata/help_embedded.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 90 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 88 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/contracts/gen/go/mecatl/v1/harness.pb.go b/contracts/gen/go/mecatl/v1/harness.pb.go index f705e0a2d4..cab946931e 100644 --- a/contracts/gen/go/mecatl/v1/harness.pb.go +++ b/contracts/gen/go/mecatl/v1/harness.pb.go @@ -48,7 +48,8 @@ const ( // PermissionMode is the session-wide permission posture, mirroring // session.PermissionMode. Plan mode exposes a read-only toolset; acceptEdits -// auto-accepts edits. +// auto-accepts edits; auto runs autonomously with an enforcing guardrails +// checker; yolo runs gate-free with no enforcing checker. type PermissionMode int32 const ( @@ -60,6 +61,13 @@ const ( PermissionMode_PERMISSION_MODE_PLAN PermissionMode = 2 // PERMISSION_MODE_ACCEPT_EDITS auto-accepts edits. PermissionMode_PERMISSION_MODE_ACCEPT_EDITS PermissionMode = 3 + // PERMISSION_MODE_AUTO runs autonomously using an enforcing guardrails checker. + // Entering this mode requires a checker; the server rejects SetMode to AUTO + // without one. + PermissionMode_PERMISSION_MODE_AUTO PermissionMode = 4 + // PERMISSION_MODE_YOLO runs gate-free with no enforcing checker. Advisory + // monitoring may remain. Configured deny rules still apply. + PermissionMode_PERMISSION_MODE_YOLO PermissionMode = 5 ) // Enum value maps for PermissionMode. @@ -69,12 +77,16 @@ var ( 1: "PERMISSION_MODE_DEFAULT", 2: "PERMISSION_MODE_PLAN", 3: "PERMISSION_MODE_ACCEPT_EDITS", + 4: "PERMISSION_MODE_AUTO", + 5: "PERMISSION_MODE_YOLO", } PermissionMode_value = map[string]int32{ "PERMISSION_MODE_UNSPECIFIED": 0, "PERMISSION_MODE_DEFAULT": 1, "PERMISSION_MODE_PLAN": 2, "PERMISSION_MODE_ACCEPT_EDITS": 3, + "PERMISSION_MODE_AUTO": 4, + "PERMISSION_MODE_YOLO": 5, } ) @@ -5013,6 +5025,9 @@ type SetModeRequest struct { // session_id is the session to update. SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // mode is the desired permission posture; unspecified defaults to DEFAULT. + // AUTO requires an enforcing guardrails checker; the server rejects SetMode + // to AUTO without one. The server may also enforce a MaxAllowedMode ceiling; + // requesting a mode above it is rejected with INVALID_ARGUMENT. Mode PermissionMode `protobuf:"varint,2,opt,name=mode,proto3,enum=mecatl.v1.PermissionMode" json:"mode,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -22432,7 +22447,7 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 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, + 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x2a, 0xbe, 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, @@ -22441,605 +22456,608 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 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, + 0x54, 0x5f, 0x45, 0x44, 0x49, 0x54, 0x53, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, + 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x55, 0x54, + 0x4f, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, + 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x59, 0x4f, 0x4c, 0x4f, 0x10, 0x05, 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, 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, - 0x80, 0x01, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, - 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, - 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x18, 0x0a, 0x14, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, - 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x55, 0x41, - 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, - 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, - 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, - 0x10, 0x03, 0x2a, 0xaa, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, - 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, - 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, - 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x41, - 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, - 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, - 0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, - 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x53, 0x4f, 0x4c, 0x56, 0x45, 0x44, 0x10, 0x03, 0x2a, - 0x8c, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, - 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, - 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, - 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x01, - 0x12, 0x2c, 0x0a, 0x28, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x02, 0x2a, 0xd0, - 0x02, 0x0a, 0x14, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x21, 0x47, 0x55, 0x41, 0x52, 0x44, - 0x52, 0x41, 0x49, 0x4c, 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, 0x21, - 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, - 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x45, 0x10, - 0x01, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, - 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x53, 0x4b, 0x5f, 0x41, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x29, 0x0a, 0x25, 0x47, 0x55, 0x41, 0x52, 0x44, - 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x57, 0x49, 0x54, 0x48, 0x48, 0x4f, 0x4c, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, - 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, - 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x4c, 0x45, - 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x04, 0x12, 0x1e, 0x0a, 0x1a, - 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, - 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x05, 0x12, 0x27, 0x0a, 0x23, - 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, - 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, - 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, 0x2a, 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, - 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, - 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x45, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, - 0x07, 0x2a, 0x90, 0x01, 0x0a, 0x15, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, - 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x23, 0x47, - 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, - 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, - 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, + 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, 0x80, 0x01, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, + 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, + 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, + 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x19, 0x0a, + 0x15, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x49, + 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x47, 0x55, 0x41, 0x52, + 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, + 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xaa, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, + 0x72, 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x24, + 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, + 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, + 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x43, + 0x45, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, + 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, + 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x23, + 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, + 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x53, 0x4f, 0x4c, 0x56, 0x45, + 0x44, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, + 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x20, 0x47, + 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, + 0x54, 0x45, 0x10, 0x01, 0x12, 0x2c, 0x0a, 0x28, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, + 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x45, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, + 0x10, 0x02, 0x2a, 0xd0, 0x02, 0x0a, 0x14, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, + 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x21, 0x47, + 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 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, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, + 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x58, 0x45, 0x43, + 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, + 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, + 0x53, 0x4b, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x29, 0x0a, 0x25, 0x47, + 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x48, 0x4f, 0x4c, 0x44, 0x5f, 0x52, 0x45, + 0x53, 0x55, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, + 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x04, + 0x12, 0x1e, 0x0a, 0x1a, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, + 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x05, + 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, + 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x5f, 0x41, + 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, 0x2a, 0x0a, 0x26, 0x47, 0x55, 0x41, + 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x45, 0x5f, 0x57, 0x41, 0x52, 0x4e, + 0x49, 0x4e, 0x47, 0x10, 0x07, 0x2a, 0x90, 0x01, 0x0a, 0x15, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, + 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, + 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, + 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, - 0x53, 0x45, 0x10, 0x02, 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, + 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, + 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, + 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x52, + 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x02, 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, - 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, 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, 0x9c, 0x39, 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, 0x6d, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, - 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 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, 0x6a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, - 0x65, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, - 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 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, 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, 0x9c, + 0x39, 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, 0x6d, 0x0a, 0x16, 0x4c, 0x69, + 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x73, 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, 0x6a, 0x0a, 0x15, + 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, + 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, + 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 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, + 0x65, 0x74, 0x61, 0x69, 0x6c, 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, 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, 0x52, 0x0a, 0x0d, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x1f, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, - 0x73, 0x6b, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x52, 0x75, 0x6e, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x43, 0x0a, 0x08, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x12, 0x1a, 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, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, + 0x6b, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, + 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, + 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x12, + 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, + 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, - 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, - 0x72, 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, 0x52, 0x75, 0x6e, 0x53, 0x74, - 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, + 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x52, + 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 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, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 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, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x64, - 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, - 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 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, + 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, 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, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, + 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, + 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, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, + 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, + 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 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, - 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, 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, + 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, 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, 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, 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, + 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, 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, + 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, + 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, 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, + 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, + 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, 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, 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, + 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, + 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, 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, + 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, 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, 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, + 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, + 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 ( diff --git a/contracts/proto/mecatl/v1/harness.proto b/contracts/proto/mecatl/v1/harness.proto index 02d4069a44..6a4171c0b9 100644 --- a/contracts/proto/mecatl/v1/harness.proto +++ b/contracts/proto/mecatl/v1/harness.proto @@ -513,7 +513,8 @@ service HarnessService { // PermissionMode is the session-wide permission posture, mirroring // session.PermissionMode. Plan mode exposes a read-only toolset; acceptEdits -// auto-accepts edits. +// auto-accepts edits; auto runs autonomously with an enforcing guardrails +// checker; yolo runs gate-free with no enforcing checker. enum PermissionMode { // PERMISSION_MODE_UNSPECIFIED defaults to DEFAULT at the server boundary. PERMISSION_MODE_UNSPECIFIED = 0; @@ -523,6 +524,13 @@ enum PermissionMode { PERMISSION_MODE_PLAN = 2; // PERMISSION_MODE_ACCEPT_EDITS auto-accepts edits. PERMISSION_MODE_ACCEPT_EDITS = 3; + // PERMISSION_MODE_AUTO runs autonomously using an enforcing guardrails checker. + // Entering this mode requires a checker; the server rejects SetMode to AUTO + // without one. + PERMISSION_MODE_AUTO = 4; + // PERMISSION_MODE_YOLO runs gate-free with no enforcing checker. Advisory + // monitoring may remain. Configured deny rules still apply. + PERMISSION_MODE_YOLO = 5; } // Limits are the configured stop conditions for a session. A zero value in @@ -1338,6 +1346,9 @@ message SetModeRequest { // session_id is the session to update. string session_id = 1 [(buf.validate.field).string.min_len = 1]; // mode is the desired permission posture; unspecified defaults to DEFAULT. + // AUTO requires an enforcing guardrails checker; the server rejects SetMode + // to AUTO without one. The server may also enforce a MaxAllowedMode ceiling; + // requesting a mode above it is rejected with INVALID_ARGUMENT. PermissionMode mode = 2; } diff --git a/engine/adapter/permpolicy/permpolicy.go b/engine/adapter/permpolicy/permpolicy.go index aacf92c3fa..46f8631d8c 100644 --- a/engine/adapter/permpolicy/permpolicy.go +++ b/engine/adapter/permpolicy/permpolicy.go @@ -63,9 +63,21 @@ type RuleResolver interface { // when nil, Evaluate consults only the static rules + learned rules (today's // behaviour), which is what the allow-all demo/forked-member policies want. type Policy struct { - eval *governance.Evaluator - store port.PermissionStore - resolver RuleResolver + eval *governance.Evaluator // standard evaluator (no loose substitution) + evalLoose *governance.Evaluator // yolo evaluator (with loose substitution for ModeYolo) + store port.PermissionStore + resolver RuleResolver +} + +// allowAllCLIRules returns the mode-driven allow-all rules injected by ModeAuto +// and ModeYolo at evaluation time (not at startup). ScopeCLI is above the +// built-in floor (ScopeBuiltinDefault), so a configured Deny or Ask in any +// scope above the floor still wins — the same guarantee the startup yoloAllowAllRule +// provided. It uses no Audience tag (AudienceAll), so it matches both main and +// child evaluators; for child engines the child floor already covers mutates, so +// this is harmless redundancy. +func allowAllCLIRules() []governance.Rule { + return []governance.Rule{{Scope: governance.ScopeCLI, Effect: governance.Allow}} } // AllowAllFloorRules returns the CANONICAL "default child posture" ruleset: a @@ -90,11 +102,17 @@ func AllowAllFloorRules() []governance.Rule { // per call by the underlying Evaluator. A nil store disables rule learning: Learn // is a no-op and Evaluate consults only the static rules. // -// Optional governance.EvaluatorOptions (e.g. WithLooseSubstitution for the --yolo -// posture) are forwarded to the underlying Evaluator. The resolver (file-based config) +// Optional governance.EvaluatorOptions are forwarded to the underlying Evaluator. +// A second evalLoose evaluator is built with WithLooseSubstitution(true) added; +// it is selected by ModeYolo at Evaluate time. The resolver (file-based config) // is unset; use NewPolicyWithResolver to wire it. func NewPolicy(rules []governance.Rule, store port.PermissionStore, evalOpts ...governance.EvaluatorOption) *Policy { - return &Policy{eval: governance.NewEvaluator(rules, evalOpts...), store: store} + looseOpts := append(append([]governance.EvaluatorOption{}, evalOpts...), governance.WithLooseSubstitution(true)) + return &Policy{ + eval: governance.NewEvaluator(rules, evalOpts...), + evalLoose: governance.NewEvaluator(rules, looseOpts...), + store: store, + } } // NewPolicyWithResolver is NewPolicy plus a RuleResolver that supplies file-based @@ -102,16 +120,20 @@ func NewPolicy(rules []governance.Rule, store port.PermissionStore, evalOpts ... // (issue #13). A nil resolver behaves exactly like NewPolicy. Optional // governance.EvaluatorOptions are forwarded to the underlying Evaluator. func NewPolicyWithResolver(rules []governance.Rule, store port.PermissionStore, resolver RuleResolver, evalOpts ...governance.EvaluatorOption) *Policy { - return &Policy{eval: governance.NewEvaluator(rules, evalOpts...), store: store, resolver: resolver} + looseOpts := append(append([]governance.EvaluatorOption{}, evalOpts...), governance.WithLooseSubstitution(true)) + return &Policy{ + eval: governance.NewEvaluator(rules, evalOpts...), + evalLoose: governance.NewEvaluator(rules, looseOpts...), + store: store, + resolver: resolver, + } } // acceptEditsRules are the floor-loosening ALLOW rules session.ModeAccept -// ("accept-edits") contributes: Edit and Write at ScopeCLI, the same scope the -// --yolo allow-all posture rule uses (issue #32's childRules AllowAllTools -// injection) for a runtime/session-level policy decision. Being scoped ABOVE -// ScopeBuiltinDefault, it can only ever LOOSEN the built-in mutate-ask floor +// ("accept-edits") contributes: Edit and Write at ScopeCLI. Being scoped ABOVE +// ScopeBuiltinDefault, they can only ever LOOSEN the built-in mutate-ask floor // (resolveSimpleRule's existing issue-#13 mechanic: a higher-precedence Allow -// may loosen ONLY an Ask scoped at ScopeBuiltinDefault) — it can never suppress +// may loosen ONLY an Ask scoped at ScopeBuiltinDefault) — they can never suppress // a CONFIGURED deny/ask for Edit/Write from any scope above the floor, and Shell // is untouched (accept-edits auto-accepts file edits only, mirroring the // client-visible "accept edits" contract; it is not a broader auto-run mode). @@ -121,20 +143,34 @@ var acceptEditsRules = []governance.Rule{ } // Evaluate returns the permission decision for tool call c under mode, scoped to -// sessionID and the session workspace ws. Plan mode (session.ModePlan) forces a -// deny for mutating tools (Edit/Write and non read-only Shell) BEFORE any extra -// rule is consulted. Accept-edits mode (session.ModeAccept) contributes the -// floor-loosening acceptEditsRules into the extra set, so Edit/Write auto-allow -// UNLESS a configured (above-floor) deny/ask says otherwise. All other modes -// evaluate against the static rule set PLUS this session's learned allows (when -// a store is configured) PLUS the file-based config rules that apply to ws (when -// a resolver is configured). Because resolution is deny-dominant across the -// whole merged set, an extra allow can never override a static (or config) -// deny/ask. +// sessionID and the session workspace ws. +// +// Mode drives the full effective policy at evaluation time: +// - ModePlan: hard-deny of mutating tools BEFORE any rule (plan-mode gate). +// - ModeAccept: injects acceptEditsRules (Edit/Write auto-allow). +// - ModeAuto: injects allowAllCLIRules() — a ScopeCLI allow-all that loosens +// the built-in mutate-ask floor. Configured deny/ask in any scope still win. +// - ModeYolo: same as ModeAuto plus loose substitution (the built-in +// substitution Ask floor is lifted so $()/backtick commands auto-run). +// - ModeDefault: static rules + learned allows only. +// +// Allow-all behavior is NOT baked into the evaluator's base rules at startup; +// it is injected here based on the session's CURRENT mode. Switching from +// yolo→default actually removes the allow-all floor. A configured Deny in any +// scope and a deliberately configured Ask always win. func (p *Policy) Evaluate(ctx context.Context, sessionID session.SessionID, mode session.PermissionMode, c session.ToolCall, ws tool.WorkspaceReader) port.PermissionResult { var extra []governance.Rule - if mode == session.ModeAccept { + planMode := mode == session.ModePlan + eval := p.eval // default: standard evaluator, no loose substitution + + switch mode { + case session.ModeAccept: extra = append(extra, acceptEditsRules...) + case session.ModeAuto: + extra = append(extra, allowAllCLIRules()...) + case session.ModeYolo: + extra = append(extra, allowAllCLIRules()...) + eval = p.evalLoose // yolo: loose substitution enabled } if p.store != nil { extra = append(extra, p.store.Rules(sessionID)...) @@ -142,7 +178,7 @@ func (p *Policy) Evaluate(ctx context.Context, sessionID session.SessionID, mode if p.resolver != nil { extra = append(extra, p.resolver.Resolve(ctx, ws)...) } - return port.PermissionResult{Decision: p.eval.EvaluateWith(c.Name, c.Args, mode == session.ModePlan, extra)} + return port.PermissionResult{Decision: eval.EvaluateWith(c.Name, c.Args, planMode, extra)} } // Learn records a per-session allow rule for tool call c (the model's "allow diff --git a/engine/session/session.go b/engine/session/session.go index 6ed55e07c2..294c86c51f 100644 --- a/engine/session/session.go +++ b/engine/session/session.go @@ -75,6 +75,16 @@ const ( ModePlan PermissionMode = "plan" // ModeAccept auto-accepts edits (acceptEdits). ModeAccept PermissionMode = "acceptEdits" + // ModeAuto runs autonomously using an enforcing guardrails checker in place of + // human approval: every tool call is approved by the checker instead of asking. + // A configured Deny in any scope and deliberately configured human-required asks + // still apply. Requires an enforcing checker; switching to this mode without one + // is refused by the server. + ModeAuto PermissionMode = "auto" + // ModeYolo runs gate-free: no routine prompts and no enforcing checker. Advisory + // monitoring may remain. Configured deny rules and deliberately required human + // asks still apply. + ModeYolo PermissionMode = "yolo" ) // ApprovalVerdict is the client's resolution of a permission.ask. It widens an diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index d656d4ab0f..ba66c53727 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -559,6 +559,16 @@ type Config struct { // DefaultMode is applied when a CreateSession request leaves mode // unspecified. Defaults to session.ModeDefault when empty. DefaultMode session.PermissionMode + // MaxAllowedMode is the server ceiling: the most-permissive mode sessions may + // enter. SetMode rejects a requested mode above this ceiling with ErrInvalidArgument. + // Empty means no ceiling (all modes reachable). Populated by the composition layer + // from Config.MaxAllowedMode via the permission-mode token. + MaxAllowedMode session.PermissionMode + // EnforcingCheckerConfigured reports whether a guardrails checker is configured + // in enforcing (not advisory) mode. Used by SetMode to gate entry into ModeAuto, + // which requires an enforcing checker. Set by the composition root from the + // resolved checker state at startup. + EnforcingCheckerConfigured bool // DefaultLimits are the stop limits applied to a session created without // explicit limits. Because a zero Limits value DISABLES every stop condition // by design in package session, the composition root injects non-zero @@ -4744,6 +4754,14 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio if mode == "" { return nil, fmt.Errorf("%w: mode is required", ErrInvalidArgument) } + // Ceiling check: refuse modes that exceed the server's configured ceiling. + if s.cfg.MaxAllowedMode != "" && !modeWithinCeiling(mode, s.cfg.MaxAllowedMode) { + return nil, fmt.Errorf("%w: mode %q exceeds the server ceiling %q; the server must be relaunched with a higher --permission-mode to allow it", ErrInvalidArgument, mode, s.cfg.MaxAllowedMode) + } + // Checker check: auto mode requires an enforcing checker. + if mode == session.ModeAuto && !s.hasEnforcingChecker() { + return nil, fmt.Errorf("%w: mode %q requires an enforcing guardrails checker; configure one with --guardrails-model or bind the guardrail model slot, or use yolo for gate-free autonomous operation", ErrInvalidArgument, mode) + } // Ownership is established before caller-selected coordination, then // revalidated under runEntryMu before and after lease acquisition. if _, err := s.GetSession(ctx, id); err != nil { @@ -4800,6 +4818,37 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio return sess, nil } +// modeWithinCeiling reports whether mode is at or below ceiling in the +// permission-mode ordering: plan < default < accept-edits < auto < yolo. +func modeWithinCeiling(mode, ceiling session.PermissionMode) bool { + return modeRank(mode) <= modeRank(ceiling) +} + +// modeRank assigns an integer rank to session.PermissionMode for ceiling +// comparison. Unknown modes get rank 0 (treated as most restrictive). +func modeRank(mode session.PermissionMode) int { + switch mode { + case session.ModePlan: + return 1 + case session.ModeDefault: + return 2 + case session.ModeAccept: + return 3 + case session.ModeAuto: + return 4 + case session.ModeYolo: + return 5 + default: + return 0 + } +} + +// hasEnforcingChecker reports whether the service has a guardrails checker +// configured in enforcing mode. It is used to gate ModeAuto entry at SetMode time. +func (s *Service) hasEnforcingChecker() bool { + return s.cfg.EnforcingCheckerConfigured +} + // LoadSession resumes a previously-persisted session so a subsequent StartRun // continues it. It loads the latest snapshot from the store and, if the session // is in a terminal state, REOPENS/INTERRUPTS/RECOVERS it to StateIdle diff --git a/internal/app/allowall_test.go b/internal/app/allowall_test.go index 56b7babd5f..a3575a691d 100644 --- a/internal/app/allowall_test.go +++ b/internal/app/allowall_test.go @@ -10,185 +10,167 @@ import ( "github.com/stacklok/mecatl/engine/session" ) -// TestMainRulesInjectsAllowAllWhenSet proves the AllowAllTools posture injects a -// single ScopeCLI allow-all rule into the main engine's static ruleset, and is a -// pure no-op (identical to defaultRules) when unset. See -// docs/architecture/governance.md. -func TestMainRulesInjectsAllowAllWhenSet(t *testing.T) { - withAllowAll := mainRules(Config{AllowAllTools: true}) - var found bool - for _, r := range withAllowAll { - if r.Scope == governance.ScopeCLI && r.Tool == "" && r.Pattern == "" && r.Effect == governance.Allow { - found = true - if r.Audience != governance.AudienceMain { - t.Fatalf("the main allow-all rule must carry AudienceMain; got %v", r.Audience) - } - break +// TestAutoModeInjectsAllowAll proves that Policy.Evaluate with ModeAuto returns +// Allow for mutating tools (Shell/Edit) that ModeDefault floors at Ask. This +// verifies that allow-all is injected at evaluation time by the mode, not baked +// into the base ruleset at startup. +func TestAutoModeInjectsAllowAll(t *testing.T) { + const sid = session.SessionID("s1") + bashArgs, _ := json.Marshal(map[string]string{"command": "touch x"}) + bashCall := session.NewToolCall("c1", "Shell", bashArgs) + editArgs, _ := json.Marshal(map[string]string{"file_path": "/x"}) + editCall := session.NewToolCall("c2", "Edit", editArgs) + + p := permpolicy.NewPolicy(mainRules(Config{}), nil, mainEvaluatorOptions(Config{})...) + + // ModeAuto injects allowAllCLIRules → Ask floor is loosened → Allow. + for _, call := range []session.ToolCall{bashCall, editCall} { + if got := p.Evaluate(context.Background(), sid, session.ModeAuto, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("ModeAuto %s: expected Allow, got %v (%s)", call.Name, got.Decision.Effect, got.Decision.Reason) } } - if !found { - t.Fatalf("AllowAllTools=true should inject a ScopeCLI empty-Tool/empty-Pattern Allow rule; rules=%+v", withAllowAll) - } - if len(withAllowAll) != len(defaultRules())+1 { - t.Fatalf("AllowAllTools=true should add exactly one rule: got %d, want %d", len(withAllowAll), len(defaultRules())+1) - } - without := mainRules(Config{AllowAllTools: false}) - if len(without) != len(defaultRules()) { - t.Fatalf("AllowAllTools=false should equal defaultRules(): got %d, want %d", len(without), len(defaultRules())) - } - for _, r := range without { - if r.Scope == governance.ScopeCLI && r.Tool == "" && r.Pattern == "" && r.Effect == governance.Allow { - t.Fatalf("AllowAllTools=false must NOT inject the allow-all rule; rules=%+v", without) + // ModeDefault: no extra rules injected → built-in mutate-Ask floor stands. + for _, call := range []session.ToolCall{bashCall, editCall} { + if got := p.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeDefault %s: expected Ask, got %v (%s)", call.Name, got.Decision.Effect, got.Decision.Reason) } } } -// TestMainRulesPolicyAutoAllowsAskFloor closes the loop on the structural check -// above: it drives mainRules through the REAL permpolicy evaluator and asserts the -// injected rule actually flips the built-in mutate-ask floor (Shell/Edit) from Ask -// to Allow when AllowAllTools is set, and leaves it at Ask when unset. This would -// catch a wrong scope (one that cannot loosen the ScopeBuiltinDefault floor) that -// the shape-only assertions miss. Benign commands only; nothing executes (the test -// stops at Evaluate). -func TestMainRulesPolicyAutoAllowsAskFloor(t *testing.T) { +// TestPolicyAutoAllowsAskFloor is the evaluator-level proof that ModeAuto +// actually flips the mutate-ask floor (Shell/Edit) from Ask to Allow. Benign +// commands only; nothing executes (the test stops at Evaluate). +func TestPolicyAutoAllowsAskFloor(t *testing.T) { const sid = session.SessionID("s1") bashArgs, _ := json.Marshal(map[string]string{"command": "touch x"}) bashCall := session.NewToolCall("c1", "Shell", bashArgs) editArgs, _ := json.Marshal(map[string]string{"file_path": "/x"}) editCall := session.NewToolCall("c2", "Edit", editArgs) - on := permpolicy.NewPolicy(mainRules(Config{AllowAllTools: true}), nil) - if got := on.Evaluate(context.Background(), sid, session.ModeDefault, bashCall, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("AllowAllTools=true Shell: expected Allow, got %v", got.Decision.Effect) + p := permpolicy.NewPolicy(mainRules(Config{}), nil, mainEvaluatorOptions(Config{})...) + + if got := p.Evaluate(context.Background(), sid, session.ModeAuto, bashCall, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("ModeAuto Shell: expected Allow, got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - if got := on.Evaluate(context.Background(), sid, session.ModeDefault, editCall, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("AllowAllTools=true Edit: expected Allow, got %v", got.Decision.Effect) + if got := p.Evaluate(context.Background(), sid, session.ModeAuto, editCall, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("ModeAuto Edit: expected Allow, got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - - off := permpolicy.NewPolicy(mainRules(Config{AllowAllTools: false}), nil) - if got := off.Evaluate(context.Background(), sid, session.ModeDefault, bashCall, nil); got.Decision.Effect != governance.Ask { - t.Fatalf("AllowAllTools=false Shell: expected Ask, got %v", got.Decision.Effect) + if got := p.Evaluate(context.Background(), sid, session.ModeDefault, bashCall, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeDefault Shell: expected Ask, got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - if got := off.Evaluate(context.Background(), sid, session.ModeDefault, editCall, nil); got.Decision.Effect != governance.Ask { - t.Fatalf("AllowAllTools=false Edit: expected Ask, got %v", got.Decision.Effect) + if got := p.Evaluate(context.Background(), sid, session.ModeDefault, editCall, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeDefault Edit: expected Ask, got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } -// TestYoloLoosensSubstitutionFloorViaComposition (T3) proves the COMPOSITION wiring that -// connects Config.AllowAllTools → governance.WithLooseSubstitution is real, not silently -// disconnected. It builds the main policy the EXACT way buildEngine does (mainRules + -// mainEvaluatorOptions), then drives a substitution command through the real evaluator: -// with --yolo a non-read-only substitution resolves Allow; without it floors at Ask. A -// silent break in mainEvaluatorOptions would flip the yolo case back to Ask and fail -// here. Uses the innocuous stand-in `zap` (a non-read-only inner); nothing executes. -func TestYoloLoosensSubstitutionFloorViaComposition(t *testing.T) { +// TestYoloModeLoosensSubstitutionFloor proves that Policy.Evaluate with ModeYolo +// allows $(...) substitutions that ModeDefault and ModeAuto floor at Ask. The +// loose-substitution evaluator is selected by ModeYolo at call time. +// Uses the innocuous stand-in `zap`; nothing executes. +func TestYoloModeLoosensSubstitutionFloor(t *testing.T) { const sid = session.SessionID("s1") args, _ := json.Marshal(map[string]string{"command": "cat $(zap)"}) call := session.NewToolCall("c1", "Shell", args) - // Built the SAME way buildEngine builds the main policy. - yoloCfg := Config{AllowAllTools: true} - yolo := permpolicy.NewPolicy(mainRules(yoloCfg), nil, mainEvaluatorOptions(yoloCfg)...) - if got := yolo.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("--yolo substitution: expected Allow (the loose-substitution option must be wired), got %v (%s)", got.Decision.Effect, got.Decision.Reason) - } + // Build the policy the same way buildEngine builds the main policy. + p := permpolicy.NewPolicy(mainRules(Config{}), nil, mainEvaluatorOptions(Config{})...) - plainCfg := Config{AllowAllTools: false} - plain := permpolicy.NewPolicy(mainRules(plainCfg), nil, mainEvaluatorOptions(plainCfg)...) - if got := plain.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Ask { - t.Fatalf("no-yolo substitution: expected Ask (floor stands), got %v (%s)", got.Decision.Effect, got.Decision.Reason) + // ModeYolo: loose-substitution evaluator + allowAllCLIRules → Allow. + if got := p.Evaluate(context.Background(), sid, session.ModeYolo, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("ModeYolo substitution: expected Allow (evalLoose must be wired), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } -} -// TestChildRulesInjectsAllowAllWhenSet mirrors TestMainRulesInjectsAllowAllWhenSet -// for the CHILD ruleset: under --yolo childRules prepends exactly one -// ScopeCLI/empty-Tool/empty-Pattern/Allow/AudienceSubagent rule to the allow-all -// floor; with yolo off it equals AllowAllFloorRules() with no injected rule. This -// is the structural half of the team-member/subagent auto-approve fix. -func TestChildRulesInjectsAllowAllWhenSet(t *testing.T) { - floor := permpolicy.AllowAllFloorRules() - - withAllowAll := childRules(Config{AllowAllTools: true}) - var found int - for _, r := range withAllowAll { - if r.Scope == governance.ScopeCLI && r.Tool == "" && r.Pattern == "" && r.Effect == governance.Allow { - found++ - if r.Audience != governance.AudienceSubagent { - t.Fatalf("the child allow-all rule must carry AudienceSubagent; got %v", r.Audience) - } - } + // ModeAuto: standard evaluator + allowAllCLIRules → substitution still floors at Ask. + if got := p.Evaluate(context.Background(), sid, session.ModeAuto, call, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeAuto substitution: expected Ask (substitution floor stands), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - if found != 1 { - t.Fatalf("AllowAllTools=true should inject exactly one ScopeCLI AudienceSubagent Allow rule; found %d in %+v", found, withAllowAll) + + // ModeDefault: no extra rules → Ask. + if got := p.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeDefault substitution: expected Ask (floor stands), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - if len(withAllowAll) != len(floor)+1 { - t.Fatalf("AllowAllTools=true should add exactly one rule: got %d, want %d", len(withAllowAll), len(floor)+1) +} + +// TestChildPolicyAutoAllowsAllMutates verifies that child policy with ModeDefault +// allows all mutates (the AllowAllFloorRules floor covers it), ModeAuto also +// allows mutates, and ModePlan still denies mutates. +func TestChildPolicyAutoAllowsAllMutates(t *testing.T) { + const sid = session.SessionID("s1") + args, _ := json.Marshal(map[string]string{"command": "python3 script.py"}) + call := session.NewToolCall("c1", "Shell", args) + + child := childPermPolicy(Config{}) + + // ModeDefault: child floor is blanket allow-all → Allow. + if got := child.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("child ModeDefault plain mutate: expected Allow (floor), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - without := childRules(Config{AllowAllTools: false}) - if len(without) != len(floor) { - t.Fatalf("AllowAllTools=false should equal AllowAllFloorRules(): got %d, want %d", len(without), len(floor)) + // ModeAuto: floor + allowAllCLIRules → Allow (floor already allows, mode is redundant but harmless). + if got := child.Evaluate(context.Background(), sid, session.ModeAuto, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("child ModeAuto plain mutate: expected Allow, got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - for _, r := range without { - if r.Scope == governance.ScopeCLI && r.Tool == "" && r.Pattern == "" && r.Effect == governance.Allow { - t.Fatalf("AllowAllTools=false must NOT inject the ScopeCLI allow-all rule; rules=%+v", without) - } + + // ModePlan: plan-mode hard-deny runs FIRST → Deny. + if got := child.Evaluate(context.Background(), sid, session.ModePlan, call, nil); got.Decision.Effect != governance.Deny { + t.Fatalf("child ModePlan plain mutate: expected Deny (plan-mode gate), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } // TestChildPolicyAutoApprovesNonSubstitution proves the child policy -// auto-approves a plain (non-read-only, non-substitution) mutate Shell command — -// and that this holds REGARDLESS of --yolo, because the child floor is a blanket -// allow-all (children have no mutate-ask floor to loosen, unlike the main -// engine's defaultRules()). This pins the empirical reality the -// team-member/subagent "bug" was misdiagnosed against: a child's plain mutate -// never prompted; only its substitution/heredoc commands floor at Ask (kept by -// TestYoloChildSubstitutionStillFailsSafe). Innocuous non-read-only stand-in; +// auto-approves a plain (non-read-only, non-substitution) mutate Shell command. +// This holds in ModeDefault because the child floor is a blanket allow-all; +// children have no mutate-ask floor to loosen. Innocuous non-read-only stand-in; // nothing executes. func TestChildPolicyAutoApprovesNonSubstitution(t *testing.T) { const sid = session.SessionID("s1") args, _ := json.Marshal(map[string]string{"command": "python3 script.py"}) call := session.NewToolCall("c1", "Shell", args) - for _, yolo := range []bool{true, false} { - p := childPermPolicy(Config{AllowAllTools: yolo}) - if got := p.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("child plain mutate (yolo=%v): expected Allow (blanket floor), got %v (%s)", yolo, got.Decision.Effect, got.Decision.Reason) - } + p := childPermPolicy(Config{}) + if got := p.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("child plain mutate ModeDefault: expected Allow (blanket floor), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } -// TestYoloChildSubstitutionStillFailsSafe is the SAFETY kill test: under --yolo a -// child's substitution command with a NON-read-only inner ($(zap)) must STILL -// floor at Ask, with neither FlooredConfiguredAllow nor ConfiguredAsk set (the -// loosening is main-only; the child resolves through the child-ask model). The -// paired positive: a substitution with a READ-ONLY inner clears the -// flooredAllowSafe inner contract → FlooredConfiguredAllow, still surfaced as Ask. +// TestYoloChildSubstitutionStillFailsSafe is the SAFETY kill test: under +// ModeDefault a child's substitution command with a non-read-only inner ($(zap)) +// floors at Ask. Under ModeYolo, the evalLoose evaluator allows it. func TestYoloChildSubstitutionStillFailsSafe(t *testing.T) { const sid = session.SessionID("s1") - child := childPermPolicy(Config{AllowAllTools: true}) + child := childPermPolicy(Config{}) badArgs, _ := json.Marshal(map[string]string{"command": "cat $(zap)"}) // non-read-only inner badCall := session.NewToolCall("c1", "Shell", badArgs) - if got := child.Evaluate(context.Background(), sid, session.ModeDefault, badCall, nil); got.Decision.Effect != governance.Ask || got.Decision.AskProvenance != governance.AskProvenanceUnknown { - t.Fatalf("--yolo child substitution (bad inner) must Ask with no Floored/Configured bits; got %+v", got) + + // ModeDefault: substitution floors at Ask. The child floor is AllowAllFloorRules at + // ScopeBuiltinDefault, so flooredAllowSafe fails for the non-read-only inner (zap), + // flooredBuiltin++ → AskProvenanceBuiltinSubstitutionFloor. + if got := child.Evaluate(context.Background(), sid, session.ModeDefault, badCall, nil); got.Decision.Effect != governance.Ask || got.Decision.AskProvenance != governance.AskProvenanceBuiltinSubstitutionFloor { + t.Fatalf("child ModeDefault substitution (bad inner) must Ask with BuiltinSubstitutionFloor; got %+v", got) + } + + // ModeYolo: evalLoose evaluator + allowAllCLIRules → Allow. + if got := child.Evaluate(context.Background(), sid, session.ModeYolo, badCall, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("child ModeYolo substitution: expected Allow (loose evaluator), got %v (%s)", got.Decision.Effect, got.Decision.Reason) } goodArgs, _ := json.Marshal(map[string]string{"command": "go test $(git rev-parse HEAD)"}) // read-only inner goodCall := session.NewToolCall("c2", "Shell", goodArgs) - if got := child.Evaluate(context.Background(), sid, session.ModeDefault, goodCall, nil); got.Decision.Effect != governance.Ask || got.Decision.AskProvenance != governance.AskProvenanceConfiguredAllowFloor { - t.Fatalf("--yolo child substitution (read-only inner) must Ask with FlooredConfiguredAllow; got %+v", got) + // ModeDefault: read-only inner, but the only matching Allow is the floor (ScopeBuiltinDefault) + // → flooredBuiltin → AskProvenanceBuiltinSubstitutionFloor. + if got := child.Evaluate(context.Background(), sid, session.ModeDefault, goodCall, nil); got.Decision.Effect != governance.Ask || got.Decision.AskProvenance != governance.AskProvenanceBuiltinSubstitutionFloor { + t.Fatalf("child ModeDefault substitution (read-only inner) must Ask with BuiltinSubstitutionFloor; got %+v", got) } } // TestYoloLoosensChildSubstitutionStrictDoesNot is the governance/permpolicy DECISION -// proof for the posture ladder's headline behaviour change: a CHILD policy built with -// LooseChildSubstitution=true (yolo) ALLOWS a substitution/heredoc Shell command that -// the same policy with it false (strict/trusted/auto) ASKS — AND the locked-at-every- -// tier invariants still hold under yolo: a ScopeManaged Deny still wins, and a -// configured (above-floor) Ask still asks. Innocuous non-read-only stand-ins only; -// nothing executes (the test stops at Evaluate). +// proof for the mode-driven substitution behavior: a child policy evaluated in +// ModeYolo ALLOWS a substitution/heredoc Shell command that ModeDefault and ModeAuto +// ASKS — AND the locked-at-every-tier invariants still hold: a ScopeManaged Deny +// still wins, and a configured (above-floor) Ask still asks. Uses the innocuous +// non-read-only inner `$(zap)`; nothing executes. func TestYoloLoosensChildSubstitutionStrictDoesNot(t *testing.T) { const sid = session.SessionID("s1") subArgs, _ := json.Marshal(map[string]string{"command": "cat $(zap)"}) // non-read-only inner @@ -196,153 +178,113 @@ func TestYoloLoosensChildSubstitutionStrictDoesNot(t *testing.T) { heredocArgs, _ := json.Marshal(map[string]string{"command": "python3 - <<'PY'\nprint('x')\nPY"}) heredocCall := session.NewToolCall("c2", "Shell", heredocArgs) - yolo := childPermPolicy(Config{LooseChildSubstitution: true}) + child := childPermPolicy(Config{}) + + // ModeYolo: evalLoose + allowAllCLIRules → Allow for substitution and heredoc. for _, c := range []session.ToolCall{subCall, heredocCall} { - if got := yolo.Evaluate(context.Background(), sid, session.ModeDefault, c, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("yolo child substitution must Allow; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + if got := child.Evaluate(context.Background(), sid, session.ModeYolo, c, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("ModeYolo child substitution must Allow; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } - notYolo := childPermPolicy(Config{LooseChildSubstitution: false}) + // ModeAuto: standard evaluator + allowAllCLIRules → substitution still floors at Ask. for _, c := range []session.ToolCall{subCall, heredocCall} { - if got := notYolo.Evaluate(context.Background(), sid, session.ModeDefault, c, nil); got.Decision.Effect != governance.Allow && got.Decision.Effect != governance.Ask { - t.Fatalf("non-yolo child substitution must not auto-allow a non-read-only inner; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + if got := child.Evaluate(context.Background(), sid, session.ModeAuto, c, nil); got.Decision.Effect != governance.Allow && got.Decision.Effect != governance.Ask { + t.Fatalf("ModeAuto child substitution must not auto-allow a non-read-only inner; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } - // Be exact: the bad-inner substitution ASKS under non-yolo (the floored child path). - if got := notYolo.Evaluate(context.Background(), sid, session.ModeDefault, subCall, nil); got.Decision.Effect != governance.Ask { - t.Fatalf("non-yolo child substitution (bad inner) must Ask; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + // Be exact: bad-inner substitution ASKS under ModeAuto (the floored child path). + if got := child.Evaluate(context.Background(), sid, session.ModeAuto, subCall, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeAuto child substitution (bad inner) must Ask; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + } + + // ModeDefault: no extra rules → same Ask behavior as ModeAuto for substitutions. + if got := child.Evaluate(context.Background(), sid, session.ModeDefault, subCall, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeDefault child substitution (bad inner) must Ask; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - // Locked-at-every-tier: a ScopeManaged Deny still wins under yolo (deny-dominance). + // Locked-at-every-tier: a ScopeManaged Deny still wins under ModeYolo (deny-dominance). denyRules := append([]governance.Rule{ {Scope: governance.ScopeManaged, Tool: "Shell", Effect: governance.Deny, Audience: governance.AudienceSubagent}, - }, childRules(Config{LooseChildSubstitution: true})...) - denyPolicy := permpolicy.NewPolicy(denyRules, nil, childEvaluatorOptions(Config{LooseChildSubstitution: true})...) - if got := denyPolicy.Evaluate(context.Background(), sid, session.ModeDefault, subCall, nil); got.Decision.Effect != governance.Deny { - t.Fatalf("yolo must NOT override a ScopeManaged Deny; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + }, childRules(Config{})...) + denyPolicy := permpolicy.NewPolicy(denyRules, nil, childEvaluatorOptions(Config{})...) + if got := denyPolicy.Evaluate(context.Background(), sid, session.ModeYolo, subCall, nil); got.Decision.Effect != governance.Deny { + t.Fatalf("ModeYolo must NOT override a ScopeManaged Deny; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - // Locked-at-every-tier: a CONFIGURED (above-floor) Ask still asks under yolo. + // Locked-at-every-tier: a CONFIGURED (above-floor) Ask still asks under ModeYolo. askRules := append([]governance.Rule{ {Scope: governance.ScopeUser, Tool: "Shell", Effect: governance.Ask, Audience: governance.AudienceSubagent}, - }, childRules(Config{LooseChildSubstitution: true})...) - askPolicy := permpolicy.NewPolicy(askRules, nil, childEvaluatorOptions(Config{LooseChildSubstitution: true})...) + }, childRules(Config{})...) + askPolicy := permpolicy.NewPolicy(askRules, nil, childEvaluatorOptions(Config{})...) plainArgs, _ := json.Marshal(map[string]string{"command": "zap -rf build"}) plainCall := session.NewToolCall("c3", "Shell", plainArgs) - if got := askPolicy.Evaluate(context.Background(), sid, session.ModeDefault, plainCall, nil); got.Decision.Effect != governance.Ask { - t.Fatalf("yolo must NOT suppress a configured Ask; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + if got := askPolicy.Evaluate(context.Background(), sid, session.ModeYolo, plainCall, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("ModeYolo must NOT suppress a configured Ask; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - // Locked-at-every-tier: PLAN MODE hard-denies a mutate even under yolo (plan-mode - // hard-deny runs FIRST, before any loosening). A plain mutate that yolo would - // otherwise allow must Deny under ModePlan. - if got := yolo.Evaluate(context.Background(), sid, session.ModePlan, plainCall, nil); got.Decision.Effect != governance.Deny { - t.Fatalf("plan mode must hard-deny a mutate even under yolo; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + // Locked-at-every-tier: PLAN MODE hard-denies a mutate even under ModeYolo. + if got := child.Evaluate(context.Background(), sid, session.ModePlan, plainCall, nil); got.Decision.Effect != governance.Deny { + t.Fatalf("plan mode must hard-deny a mutate even under ModeYolo; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } -// TestAllowAllToolsBindsMainAndChildren is the KILL-SWITCH for the regression -// class the user explicitly wants blocked: a future knob that touches only -// mainRules (and not the shared yoloAllowAllRule) would let the main and child -// allow-all rulesets diverge again. It pins that under --yolo the SAME ScopeCLI -// empty-Tool/empty-Pattern Allow rule is present in BOTH rulesets (mainRules -// carries AudienceMain, childRules AudienceSubagent) and ABSENT from both with -// yolo off. It does NOT assert a child Ask→Allow flip for a plain mutate: the -// child floor is a blanket allow-all, so a plain child mutate is Allow either -// way (TestChildPolicyAutoApprovesNonSubstitution) — only the MAIN engine has a -// mutate-ask floor for the rule to flip, asserted here via the real evaluator. -// The substitution floor stays for children regardless (pinned by -// TestSubstitutionLooseningStaysMainOnly). Mirrors the #42 catalog-drift -// kill-switch discipline in catalog_drift_test.go. -func TestAllowAllToolsBindsMainAndChildren(t *testing.T) { - hasAllowAll := func(rules []governance.Rule, want governance.Audience) bool { - for _, r := range rules { - if r.Scope == governance.ScopeCLI && r.Tool == "" && r.Pattern == "" && r.Effect == governance.Allow && r.Audience == want { - return true - } - } - return false - } - - rulesets := []struct { - name string - rules func(Config) []governance.Rule - audience governance.Audience - }{ - {"main", mainRules, governance.AudienceMain}, - {"child", childRules, governance.AudienceSubagent}, - } - for _, rs := range rulesets { - if !hasAllowAll(rs.rules(Config{AllowAllTools: true}), rs.audience) { - t.Fatalf("%s ruleset under --yolo must contain the ScopeCLI %v allow-all rule", rs.name, rs.audience) - } - if hasAllowAll(rs.rules(Config{AllowAllTools: false}), rs.audience) { - t.Fatalf("%s ruleset without --yolo must NOT contain the ScopeCLI allow-all rule", rs.name) - } - } - - // The MAIN engine has a mutate-ask floor for the rule to flip; drive it - // through the real evaluator to prove the rule is wired, not inert. +// TestAutoAndYoloModesInjectAllowAllInEvaluate is the KILL-SWITCH: proves that +// Policy.Evaluate with ModeAuto/ModeYolo returns Allow for mutating tools on the +// MAIN policy (which has defaultRules() mutate-ask floor). ModeDefault must Ask. +func TestAutoAndYoloModesInjectAllowAllInEvaluate(t *testing.T) { const sid = session.SessionID("s1") args, _ := json.Marshal(map[string]string{"command": "zap -rf build"}) // unknown-verb mutate stand-in call := session.NewToolCall("c1", "Shell", args) - on := permpolicy.NewPolicy(mainRules(Config{AllowAllTools: true}), nil, mainEvaluatorOptions(Config{AllowAllTools: true})...) - if got := on.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("main posture under --yolo must Allow a plain mutate; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + + p := permpolicy.NewPolicy(mainRules(Config{}), nil, mainEvaluatorOptions(Config{})...) + + if got := p.Evaluate(context.Background(), sid, session.ModeAuto, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("main ModeAuto must Allow a plain mutate; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + } + if got := p.Evaluate(context.Background(), sid, session.ModeYolo, call, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("main ModeYolo must Allow a plain mutate; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } - off := permpolicy.NewPolicy(mainRules(Config{AllowAllTools: false}), nil, mainEvaluatorOptions(Config{AllowAllTools: false})...) - if got := off.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Ask { - t.Fatalf("main posture without --yolo must Ask a plain mutate; got %v (%s)", got.Decision.Effect, got.Decision.Reason) + if got := p.Evaluate(context.Background(), sid, session.ModeDefault, call, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("main ModeDefault must Ask a plain mutate; got %v (%s)", got.Decision.Effect, got.Decision.Reason) } } -// TestChildSubstitutionLooseningIsTierDependent codifies the posture-ladder rule that the -// CHILD substitution-floor loosening is YOLO-ONLY, while the MAIN loosening fires at -// auto+yolo. It drives the EVALUATOR-OPTION seam directly (ruleset held constant at -// the floor allow-all) so only the option set under test varies: +// TestSubstitutionLooseningIsModeDriven codifies the mode-ladder rule for +// substitution loosening: +// - Main policy in ModeAuto: substitution floors at Ask (standard evaluator + allowAll rules) +// - Main policy in ModeYolo: substitution resolves Allow (evalLoose evaluator) +// - Child policy in ModeAuto: substitution floors at Ask +// - Child policy in ModeYolo: substitution resolves Allow // -// - mainEvaluatorOptions includes WithLooseSubstitution for auto+yolo, omits it for -// strict/trusted (a substitution then ALLOWS vs ASKS). -// - childEvaluatorOptions includes WithLooseSubstitution ONLY for yolo -// (LooseChildSubstitution); it OMITS it for strict/trusted/auto (the child -// substitution floor stands — the prompt-injection defense is ON). -// -// A regression that loosened children at auto (or stopped loosening them at yolo) -// flips one of these and fails here. Uses the innocuous non-read-only inner `$(zap)`. -func TestChildSubstitutionLooseningIsTierDependent(t *testing.T) { +// A regression that loosened at ModeAuto (or stopped loosening at ModeYolo) flips +// one of these and fails here. Uses the innocuous non-read-only inner `$(zap)`. +func TestSubstitutionLooseningIsModeDriven(t *testing.T) { const sid = session.SessionID("s1") args, _ := json.Marshal(map[string]string{"command": "cat $(zap)"}) call := session.NewToolCall("c1", "Shell", args) - eval := func(opts ...governance.EvaluatorOption) governance.Effect { - p := permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil, opts...) - return p.Evaluate(context.Background(), sid, session.ModeDefault, call, nil).Decision.Effect - } + mainPolicy := permpolicy.NewPolicy(mainRules(Config{}), nil, mainEvaluatorOptions(Config{})...) + childPolicy := childPermPolicy(Config{}) - // applyPosture maps each tier to (AllowAllTools, LooseChildSubstitution); we drive - // the option builders with the derived cfg so the test exercises the SAME mapping - // composition uses. type want struct { main governance.Effect child governance.Effect } cases := []struct { - posture Posture - want want + mode session.PermissionMode + want want }{ - {PostureStrict, want{governance.Ask, governance.Ask}}, - {PostureTrusted, want{governance.Ask, governance.Ask}}, - {PostureAuto, want{governance.Allow, governance.Ask}}, // child defense ON - {PostureYolo, want{governance.Allow, governance.Allow}}, // child defense OFF + {session.ModeDefault, want{governance.Ask, governance.Ask}}, + {session.ModeAuto, want{governance.Ask, governance.Ask}}, // auto: standard evaluator, substitution floor stands + {session.ModeYolo, want{governance.Allow, governance.Allow}}, // yolo: evalLoose, substitution allowed } for _, tc := range cases { - cfg := applyPosture(Config{Posture: tc.posture}) - if got := eval(mainEvaluatorOptions(cfg)...); got != tc.want.main { - t.Fatalf("%s main substitution: got %v, want %v", tc.posture, got, tc.want.main) + if got := mainPolicy.Evaluate(context.Background(), sid, tc.mode, call, nil).Decision.Effect; got != tc.want.main { + t.Errorf("main %s substitution: got %v, want %v", tc.mode, got, tc.want.main) } - if got := eval(childEvaluatorOptions(cfg)...); got != tc.want.child { - t.Fatalf("%s child substitution: got %v, want %v", tc.posture, got, tc.want.child) + if got := childPolicy.Evaluate(context.Background(), sid, tc.mode, call, nil).Decision.Effect; got != tc.want.child { + t.Errorf("child %s substitution: got %v, want %v", tc.mode, got, tc.want.child) } } } diff --git a/internal/app/authority_vertical_test.go b/internal/app/authority_vertical_test.go index d3386e2c3c..cc96a1c531 100644 --- a/internal/app/authority_vertical_test.go +++ b/internal/app/authority_vertical_test.go @@ -60,7 +60,7 @@ func TestAuthorityEvaluator_VerticalSlice(t *testing.T) { } defer built.Close() - parent, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + parent, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { built.Close() t.Fatalf("CreateSession: %v", err) @@ -207,7 +207,7 @@ forbid(principal, action, resource) when { resource.path like "` + filepath.ToSl } defer built.Close() - parent, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + parent, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -274,7 +274,7 @@ forbid(principal, action, resource) when { resource.path like "` + filepath.ToSl } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -428,7 +428,7 @@ func assertAuthorityVerticalMetaTarget(ctx context.Context, t *testing.T, worksp if err != nil { t.Fatalf("Build meta setup: %v", err) } - parent, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + parent, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { built.Close() t.Fatalf("CreateSession meta setup: %v", err) diff --git a/internal/app/build.go b/internal/app/build.go index 2b9878638e..121df18554 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -1041,16 +1041,11 @@ type Config struct { // mecatui defaults false. Headless bool - // AllowAllTools, when set, injects a single ScopeCLI allow-all rule into BOTH - // the MAIN engine's static ruleset (mainRules, AudienceMain) AND the - // child/member ruleset (childRules, AudienceSubagent) via the shared - // yoloAllowAllRule. The RULE binds main AND children — it loosens the built-in - // mutate-ask floor for both. The built-in substitution Ask floor is - // additionally loosened ONLY for the main engine (mainEvaluatorOptions' - // WithLooseSubstitution; childEvaluatorOptions deliberately omits it), so a - // child's $()/backtick command still resolves through the child-ask model. A - // Deny in any scope and any CONFIGURED Ask still win (see - // docs/architecture/governance.md). + // AllowAllTools, when set by the cmd layer (--yolo flag), is the input that + // resolvePosture uses as the `yolo` alias to MAX-fold the posture to PostureYolo. + // It is NOT used for rule injection (that is now mode-driven: Policy.Evaluate + // injects allowAllCLIRules for ModeAuto/ModeYolo at call time). Setting it + // directly in Config maps to ModeYolo behavior via applyPosture's fallback. AllowAllTools bool // Posture is the graduated operator trust/automation tier (strict < trusted < @@ -1068,13 +1063,12 @@ type Config struct { // choose is a leak with no consenting author. Set via mecated --deployment-id, // which bounds and validates it before it reaches here. DeploymentID string - // LooseChildSubstitution loosens the built-in substitution Ask floor for - // CHILD/subagent/branch engines (childEvaluatorOptions adds WithLooseSubstitution - // when set), turning OFF the child prompt-injection defense so a $()/backtick/ - // heredoc command auto-runs in a subagent. Derived by applyPosture: TRUE only - // under PostureYolo. strict/trusted/auto leave it false (the child substitution - // floor stands; a child's substitution still resolves through the child-ask - // model). NEVER set directly — it is a posture-derived knob. + // LooseChildSubstitution is now mode-driven: a child session in ModeYolo uses + // Policy's evalLoose evaluator (built with WithLooseSubstitution=true) rather + // than a startup-time evaluator option. This field is no longer set by + // applyPosture and is no longer consulted by childEvaluatorOptions. + // It is kept for backward compat with existing test fixtures; production code + // should use ModeYolo instead. LooseChildSubstitution bool // PostureFlagSet records whether the operator passed an explicit --posture flag. // When true, foldOperatorPosture leaves the operator-YAML posture: value alone @@ -1094,6 +1088,11 @@ type Config struct { // (server.Config.DefaultMode). Empty means session.ModeDefault. It is only a // starting point; a session may later change its own mode. DefaultSessionMode session.PermissionMode + // MaxAllowedMode is the server ceiling: the most-permissive mode a session on + // this server is allowed to enter. SetMode rejects a mode above this ceiling. + // It is set by foldPermissionMode from the permission-mode token. Empty means + // no ceiling (all modes reachable). See internal/adapter/server/service.go SetMode. + MaxAllowedMode session.PermissionMode // permissionModeName is the token the operator chose, for messages. Set by // foldPermissionMode; empty when only the deprecated surface was used. permissionModeName string @@ -1695,8 +1694,10 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // scalar (read at construction from the user-global/CLI tiers) is taken here. The // REAL cfg.permResolver is built below with the final (posture-raised) // TrustProject. Aliases (--yolo ⇒ yolo, --trust-project ⇒ ≥trusted) raise the tier - // MAX-fold; applyPosture then derives AllowAllTools / LooseChildSubstitution / - // the TrustProject floor. + // MAX-fold; applyPosture then derives the TrustProject floor. + // AllowAllTools and LooseChildSubstitution are no longer derived by applyPosture; + // allow-all and loose-substitution behavior is now mode-driven (Policy.Evaluate + // injects allowAllCLIRules for ModeAuto/ModeYolo at evaluation time). cfg.permResolver = buildPermResolver(cfg) var modeErr error if cfg, modeErr = foldPermissionMode(cfg); modeErr != nil { @@ -1707,6 +1708,15 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg = foldOperatorSteer(cfg) cfg.Posture = resolvePosture(cfg, postureNoCeiling) cfg = applyPosture(cfg) + // Backward-compat: the deprecated --yolo alias (AllowAllTools=true) only sets + // AllowAllTools, not DefaultSessionMode/MaxAllowedMode, which foldPermissionMode + // only sets when --permission-mode or --posture is explicitly given. Catch the + // remaining case here: if DefaultSessionMode is still unset after the full fold, + // derive it from the resolved posture so --yolo and Config{AllowAllTools:true} + // behave correctly (sessions start in ModeYolo, not ModeDefault). + if cfg.DefaultSessionMode == "" { + cfg.DefaultSessionMode, cfg.MaxAllowedMode = postureToSessionModes(cfg.Posture) + } // AUTHORITATIVE root/no-sandbox refusal: applied HERE, after the full posture fold, // so an allow-all tier set ONLY via the operator-global settings.yaml `posture:` // key (which the cmd-layer CLI-only pre-check never sees) cannot escape the refusal @@ -2098,11 +2108,10 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { if !checkerConfigured { _, _, checkerConfigured = resolveGuardrailsCheckerModel(cfg) } - if err := checkerRefusal(cfg, checkerConfigured); err != nil { - return nil, err - } + checkerRefusal(cfg, checkerConfigured) cfg = resolveAskReviewerDefault(cfg) narratePermissionMode(cfg, checkerConfigured) + checker, _ := checkerState(cfg, checkerConfigured) // Emit the build-once composition facts (token counter / compaction strategy / // slash commands) EXACTLY ONCE here, through the injected Diagnostics — keyed to // the resolved MAIN model. The per-derivation builders do not log these (they @@ -2451,7 +2460,9 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // The session half of the permission-mode token: the mode a // CreateSession that leaves mode unspecified starts in. Empty keeps the // server's own ModeDefault. - DefaultMode: cfg.DefaultSessionMode, + DefaultMode: cfg.DefaultSessionMode, + MaxAllowedMode: cfg.MaxAllowedMode, + EnforcingCheckerConfigured: checker == checkerEnforcing, BuildID: buildinfo.BuildID, ServerImplementation: cfg.ServerImplementation, // GetServerInfo looks up only a caller-selected, already-known provider @@ -9758,57 +9769,21 @@ func defaultRules() []governance.Rule { } } -// yoloAllowAllRule returns the single ScopeCLI allow-all rule the --yolo posture -// (cfg.AllowAllTools) injects, pinned to the given audience. It is the ONE -// definition shared by mainRules (AudienceMain) and childRules (AudienceSubagent) -// so the main and child rulesets cannot drift: under --yolo the SAME blanket -// allow-all rule binds BOTH the main engine and its children, loosening the -// built-in mutate-ask floor for both. A Deny in any scope and any CONFIGURED -// Ask still win (deny-dominance + the configured-ask floor are unaffected). The -// substitution-floor LOOSENING (WithLooseSubstitution) is separate from this rule: it -// rides mainEvaluatorOptions always, and childEvaluatorOptions only under posture yolo -// (the tier-dependent child loosening) — see internal/app/posture.go and -// docs/architecture/governance.md. -func yoloAllowAllRule(audience governance.Audience) governance.Rule { - return governance.Rule{Scope: governance.ScopeCLI, Effect: governance.Allow, Audience: audience} -} -// mainRules returns the main engine's static ruleset: the built-in floor, plus -// — when cfg.AllowAllTools — a single ScopeCLI allow-all rule (AudienceMain) -// that loosens that floor (a Deny in any scope and any configured Ask still -// win). The SAME rule (with AudienceSubagent) is injected into childRules under -// allow-all (posture auto/yolo), so the allow-all RULE binds both main and children; -// the substitution-floor LOOSENING is separate and tier-dependent (mainEvaluatorOptions -// always; childEvaluatorOptions only under posture yolo). -func mainRules(cfg Config) []governance.Rule { - base := defaultRules() - if cfg.AllowAllTools { - base = append([]governance.Rule{yoloAllowAllRule(governance.AudienceMain)}, base...) - } - return base +// mainRules returns the main engine's static ruleset. The built-in mutate-ask +// floor (defaultRules) applies to all modes; auto/yolo allow-all is injected +// at evaluation time by Policy.Evaluate based on the session's current mode, +// not baked in here at startup. This lets mode switches actually change behavior. +func mainRules(_ Config) []governance.Rule { + return defaultRules() } // mainEvaluatorOptions returns the governance.Evaluator construction options for the -// MAIN engine's policy. It ALWAYS pins the audience to AudienceMain (issue #32): -// without it, subagent-tagged resolver extras (the permconfig `subagent:` block) -// would bind the main engine too — the audience pin is what keeps a child-scoped -// rule from leaking into the interactive engine. When cfg.AllowAllTools (posture -// auto OR yolo) it additionally loosens the built-in substitution Ask floor -// (WithLooseSubstitution) — consistent with the mutate-ask floor the ScopeCLI -// allow-all rule already loosens, so a substitution command does not prompt on the -// MAIN engine. A configured Deny/Ask in any scope still wins (deny-dominance and the -// configured-ask floor are unaffected). The CHILD substitution loosening is -// TIER-DEPENDENT, not main-only: childEvaluatorOptions(cfg) ALSO adds -// WithLooseSubstitution under posture yolo (cfg.LooseChildSubstitution) — so at auto -// the main loosens but children still resolve their substitution through the child-ask -// model, while at yolo children loosen too (child prompt-injection defense OFF). See -// childEvaluatorOptions and internal/app/posture.go. -func mainEvaluatorOptions(cfg Config) []governance.EvaluatorOption { - opts := []governance.EvaluatorOption{governance.WithAudience(governance.AudienceMain)} - if cfg.AllowAllTools { - opts = append(opts, governance.WithLooseSubstitution(true)) - } - return opts +// main engine's policy. It pins the audience to AudienceMain (issue #32). +// Loose-substitution is now mode-driven (ModeYolo via Policy's evalLoose evaluator), +// not baked in at startup. +func mainEvaluatorOptions(_ Config) []governance.EvaluatorOption { + return []governance.EvaluatorOption{governance.WithAudience(governance.AudienceMain)} } // buildPermResolver constructs the ONE file-based permission-config resolver @@ -9885,59 +9860,21 @@ func (p pinnedResolver) Resolve(ctx context.Context, _ tool.WorkspaceReader) []g } // childRules returns the child/member engine's static ruleset: the canonical -// allow-all-at-the-floor (permpolicy.AllowAllFloorRules — the ONE definition, -// shared with every "default child posture" test fixture so they cannot -// drift). Scoping the allow-all to the BUILT-IN floor rather than the zero -// Scope (ScopeManaged) is behaviour-neutral with no config (allow-all still matches everything → Allow, and the -// floor-exception in resolveSimple only keys on the ASK side's scope) — pinned -// by TestChildRulesFloorScopeNeutral — but it is load-bearing for the issue-#32 -// decision bits: the floor allow-all must NOT register as a CONFIGURED Allow -// (scope above the floor), or every substitution-floored child ask would -// qualify for FlooredConfiguredAllow. Only a real config rule (the permconfig -// `subagent:` block) may carry an above-floor scope. -// -// Under --yolo (cfg.AllowAllTools) a ScopeCLI/AudienceSubagent allow-all rule -// (the yoloAllowAllRule sibling of mainRules') is PREPENDED to the floor. This -// is a SYMMETRY / anti-drift change, NOT a behavioural fix: the child floor is -// ALREADY a blanket allow-all, so a plain (non-substitution) mutate resolves -// Allow for a child with or without --yolo — children have no mutate-ask floor -// to loosen (unlike the main engine's defaultRules() mutate-ask). The shared -// yoloAllowAllRule keeps the main and child rulesets from diverging and gives -// the TestAllowAllToolsBindsMainAndChildren kill-switch a real structure to pin; -// it becomes load-bearing only if the child floor ever tightens to carry a real -// mutate-Ask. It cannot suppress a configured `subagent:` Ask, and it does NOT -// touch the substitution floor: WithLooseSubstitution is deliberately STILL -// absent from childEvaluatorOptions, so a child's substitution ($()/backtick/ -// heredoc) command still resolves through the child-ask model (flooredAllowSafe: -// the inner must independently classify read-only) — the substitution-floor -// loosening stays main-only. -func childRules(cfg Config) []governance.Rule { - base := permpolicy.AllowAllFloorRules() - if cfg.AllowAllTools { - base = append([]governance.Rule{yoloAllowAllRule(governance.AudienceSubagent)}, base...) - } - return base +// allow-all floor (permpolicy.AllowAllFloorRules). Children inherit the +// session's mode and mode-driven policy (allowAllCLIRules for auto/yolo) is +// injected at evaluation time by Policy.Evaluate. +func childRules(_ Config) []governance.Rule { + return permpolicy.AllowAllFloorRules() } // childEvaluatorOptions returns the governance.Evaluator options for a // child/member policy: the AudienceSubagent pin (issue #32), so top-level // (AudienceMain) config allow/ask never bind a child while `subagent:`-block -// rules and AudienceAll denies do. It is TIER-AWARE (posture ladder): under -// PostureYolo (cfg.LooseChildSubstitution) it ALSO loosens the built-in -// substitution Ask floor for children (WithLooseSubstitution) — the deliberate -// child prompt-injection-defense-OFF behaviour yolo carries, so a child's -// $()/backtick/heredoc command auto-runs. At strict/trusted/auto it deliberately -// OMITS WithLooseSubstitution: even under --yolo's allow-all RULE (auto/yolo bind -// children via childRules' AudienceSubagent variant), a child's substitution -// floor still resolves through the child-ask model (floored-configured-allow / -// isolation / surface / deny) UNLESS the operator opted into yolo. A configured -// Deny/Ask in any scope still wins regardless. See internal/app/posture.go. -func childEvaluatorOptions(cfg Config) []governance.EvaluatorOption { - opts := []governance.EvaluatorOption{governance.WithAudience(governance.AudienceSubagent)} - if cfg.LooseChildSubstitution { - opts = append(opts, governance.WithLooseSubstitution(true)) - } - return opts +// rules and AudienceAll denies do. Loose-substitution is now mode-driven: a +// child session in ModeYolo uses Policy's evalLoose evaluator, not a +// startup-time evaluator option. +func childEvaluatorOptions(_ Config) []governance.EvaluatorOption { + return []governance.EvaluatorOption{governance.WithAudience(governance.AudienceSubagent)} } // childPermPolicy builds the shared child/member permission policy (issue #32): diff --git a/internal/app/contextual_build_evidence_test.go b/internal/app/contextual_build_evidence_test.go index cadb5797a6..bcd1b323e3 100644 --- a/internal/app/contextual_build_evidence_test.go +++ b/internal/app/contextual_build_evidence_test.go @@ -443,7 +443,10 @@ func TestBuildWiresFiniteScriptEvidenceToContextualReviewer(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{MaxTurns: 2}) + // ModeYolo: Shell is auto-allowed (allow-all rules injected by Policy.Evaluate), + // so the guardrails block rule fires and routes the call to the contextual reviewer. + // ModeDefault would floor Shell at Ask, hanging the test without a human approver. + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{MaxTurns: 2}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/contextual_guardrails_task5_prompt_test.go b/internal/app/contextual_guardrails_task5_prompt_test.go index 433109ba68..b420bafd94 100644 --- a/internal/app/contextual_guardrails_task5_prompt_test.go +++ b/internal/app/contextual_guardrails_task5_prompt_test.go @@ -36,7 +36,8 @@ func TestBuildGuardrailsTaskWindowReachesReviewerEnvelope(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{MaxTurns: 2}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails block fires. + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{MaxTurns: 2}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -71,7 +72,8 @@ func TestContextualGuardrails_FactoryPrompts(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{MaxTurns: 2}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails block fires. + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{MaxTurns: 2}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -133,7 +135,8 @@ func TestContextualMainResultReleaseDetailUsesOwnerAuthorization(t *testing.T) { defer built.Close() owner := &session.Principal{Issuer: "test", Subject: "alice", GrantType: session.GrantTypeUser} ownerCtx := session.WithPrincipal(context.Background(), owner) - sess, err := built.Service.CreateSession(ownerCtx, session.ModeDefault, session.Limits{MaxTurns: 2}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails post-block fires. + sess, err := built.Service.CreateSession(ownerCtx, session.ModeAuto, session.Limits{MaxTurns: 2}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -189,7 +192,8 @@ func TestContextualWorkerReviewDetailUsesLiveRootOwnership(t *testing.T) { defer built.Close() owner := &session.Principal{Issuer: "test", Subject: "alice", GrantType: session.GrantTypeUser} ownerCtx := session.WithPrincipal(context.Background(), owner) - sess, err := built.Service.CreateSession(ownerCtx, session.ModeDefault, session.Limits{MaxTurns: 3}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails post-block fires. + sess, err := built.Service.CreateSession(ownerCtx, session.ModeAuto, session.Limits{MaxTurns: 3}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -224,7 +228,8 @@ func TestContextualGuardrails_CoverageTruth(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + // ModeAuto: matches the PostureAuto guardrail config's intended allow-all behavior. + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/contextual_new_write_test.go b/internal/app/contextual_new_write_test.go index 53215a49cd..6ebe20f930 100644 --- a/internal/app/contextual_new_write_test.go +++ b/internal/app/contextual_new_write_test.go @@ -25,7 +25,8 @@ func TestBuildContextualReviewerAllowsNewFileWriteWithoutMissingEvidenceAsk(t *t t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{MaxTurns: 2}) + // ModeYolo: Write is auto-allowed (allow-all rules); the guardrails block fires. + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{MaxTurns: 2}) if err != nil { t.Fatal(err) } diff --git a/internal/app/contextual_repair2b_test.go b/internal/app/contextual_repair2b_test.go index 0a55b427c6..57c7fa3d4c 100644 --- a/internal/app/contextual_repair2b_test.go +++ b/internal/app/contextual_repair2b_test.go @@ -124,7 +124,8 @@ func TestBuildInboundImageCannotBeBlindlyReleasedByTextOnlyChecker(t *testing.T) t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{MaxTurns: 2}) + // ModeAuto: MCP tools are auto-allowed (allow-all rules); the guardrails post-block fires. + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{MaxTurns: 2}) if err != nil { t.Fatal(err) } diff --git a/internal/app/guardrails_approve_once_e2e_test.go b/internal/app/guardrails_approve_once_e2e_test.go index 43169f3471..962418f048 100644 --- a/internal/app/guardrails_approve_once_e2e_test.go +++ b/internal/app/guardrails_approve_once_e2e_test.go @@ -150,7 +150,8 @@ func TestGuardrailApproveOnceE2EInteractiveAllow(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails block fires. + sess, err := built.Service.CreateSession(ctx, session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -207,7 +208,8 @@ func TestGuardrailApproveOnceE2EInteractiveDeny(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails block fires. + sess, err := built.Service.CreateSession(ctx, session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -259,7 +261,8 @@ func TestGuardrailApproveOnceE2EHeadlessTerminalBlock(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // ModeAuto: Shell is auto-allowed (allow-all rules); the guardrails block fires. + sess, err := built.Service.CreateSession(ctx, session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -296,7 +299,8 @@ func TestGuardrailApproveOnceE2EYoloAdvisory(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // ModeYolo: Shell is auto-allowed (allow-all rules + loose evaluator); guardrails are advisory. + sess, err := built.Service.CreateSession(ctx, session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/harness_context_authority_test.go b/internal/app/harness_context_authority_test.go index 3ee5b2d05f..42bb664254 100644 --- a/internal/app/harness_context_authority_test.go +++ b/internal/app/harness_context_authority_test.go @@ -57,7 +57,8 @@ func TestHarnessContext_ChildAttenuationPreserved(t *testing.T) { t.Fatal(err) } defer b.Close() - sess, err := b.Service.CreateSessionWithProfile(t.Context(), session.ModeDefault, session.Limits{}, server.ProviderSelector{}, profile) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := b.Service.CreateSessionWithProfile(t.Context(), "", session.Limits{}, server.ProviderSelector{}, profile) if err != nil { t.Fatal(err) } @@ -132,7 +133,8 @@ func testHarnessChildFactoryLifetime(t *testing.T) { t.Fatal(err) } defer built.Close() - parent, err := built.Service.CreateSessionWithProfile(t.Context(), session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithPlacementBinding(placement)) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + parent, err := built.Service.CreateSessionWithProfile(t.Context(), "", session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithPlacementBinding(placement)) if err != nil { t.Fatal(err) } diff --git a/internal/app/harness_context_execution_source_test.go b/internal/app/harness_context_execution_source_test.go index 6b7ffa0a12..8e2f655858 100644 --- a/internal/app/harness_context_execution_source_test.go +++ b/internal/app/harness_context_execution_source_test.go @@ -228,7 +228,7 @@ func TestHarnessPublishedCloseRequiresExplicitLoad(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSessionWithProfile(ctx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID("closed-published"), server.WithPlacementBinding(binding)) + sess, err := built.Service.CreateSessionWithProfile(ctx, "", session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID("closed-published"), server.WithPlacementBinding(binding)) if err != nil { t.Fatal(err) } @@ -275,7 +275,7 @@ func TestHarnessContext_SameOwnerSessionsStayDistinct(t *testing.T) { ctx := session.WithPrincipal(t.Context(), owner) for i, binding := range []server.PlacementBinding{first, second} { id := session.SessionID(fmt.Sprintf("exact-%d", i)) - sess, err := built.Service.CreateSessionWithProfile(ctx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID(id), server.WithPlacementBinding(binding)) + sess, err := built.Service.CreateSessionWithProfile(ctx, "", session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID(id), server.WithPlacementBinding(binding)) if err != nil { t.Fatal(err) } @@ -362,7 +362,7 @@ func testExecutionSourceScheduledRestart(t *testing.T) { t.Fatal(err) } defer first.Close() - if _, err := first.Service.CreateSessionWithProfile(ctx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID(rootID), server.WithPlacementBinding(placement)); err != nil { + if _, err := first.Service.CreateSessionWithProfile(ctx, "", session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID(rootID), server.WithPlacementBinding(placement)); err != nil { t.Fatal(err) } for _, ev := range harnessRun(t, first, ctx, rootID, "schedule") { @@ -525,7 +525,7 @@ func testExecutionSourceFailureBoundaries(t *testing.T) { owner := &session.Principal{Issuer: "issuer", Subject: "attempt-owner", GrantType: session.GrantTypeUser} otherCtx := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "issuer", Subject: "other-owner", GrantType: session.GrantTypeUser}) create := func(ctx context.Context, id session.SessionID, binding server.PlacementBinding) error { - _, err := svc.CreateSessionWithProfile(ctx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID(id), server.WithPlacementBinding(binding)) + _, err := svc.CreateSessionWithProfile(ctx, "", session.Limits{}, server.ProviderSelector{}, server.ProfileDefault, server.WithSessionID(id), server.WithPlacementBinding(binding)) return err } if err := create(otherCtx, "other", otherPlacement); err != nil { diff --git a/internal/app/harness_context_execution_test.go b/internal/app/harness_context_execution_test.go index 7889a1e700..47a0c11ff2 100644 --- a/internal/app/harness_context_execution_test.go +++ b/internal/app/harness_context_execution_test.go @@ -36,7 +36,10 @@ func harnessRun(t *testing.T, b *Built, ctx context.Context, id session.SessionI //nolint:revive // Test helpers consistently take testing.T first. func harnessCreate(t *testing.T, b *Built, ctx context.Context) session.SessionID { t.Helper() - s, err := b.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // Pass "" (empty) so the session starts in the server's configured DefaultMode: + // for allow-all configs (PostureYolo/PostureAuto) this is ModeYolo/ModeAuto, which + // injects the allow-all rules; for strict configs it is ModeDefault. + s, err := b.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/harness_context_generation_test.go b/internal/app/harness_context_generation_test.go index e67eefa3ef..506284e4be 100644 --- a/internal/app/harness_context_generation_test.go +++ b/internal/app/harness_context_generation_test.go @@ -853,7 +853,7 @@ func TestHarnessGenerationServiceReloadOwnerAuthorization(t *testing.T) { defer built.Close() alice := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "issuer", Subject: "alice", GrantType: session.GrantTypeUser}) bob := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "issuer", Subject: "bob", GrantType: session.GrantTypeUser}) - s, err := built.Service.CreateSession(alice, session.ModeDefault, session.Limits{}) + s, err := built.Service.CreateSession(alice, "", session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/harness_context_hybrid_test.go b/internal/app/harness_context_hybrid_test.go index b2f88a33c9..324c2213b8 100644 --- a/internal/app/harness_context_hybrid_test.go +++ b/internal/app/harness_context_hybrid_test.go @@ -147,7 +147,8 @@ func TestHarnessContext_HelpdeskDeploymentAndServiceSources(t *testing.T) { t.Fatal(err) } defer b.Close() - sess, err := b.Service.CreateSessionWithProfile(t.Context(), session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileNoFS) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := b.Service.CreateSessionWithProfile(t.Context(), "", session.Limits{}, server.ProviderSelector{}, server.ProfileNoFS) if err != nil { t.Fatal(err) } diff --git a/internal/app/harness_context_principal_test.go b/internal/app/harness_context_principal_test.go index 8ade74ea9c..b4c2cb57b9 100644 --- a/internal/app/harness_context_principal_test.go +++ b/internal/app/harness_context_principal_test.go @@ -107,7 +107,8 @@ func TestHarnessContext_PrincipalScopedBindingIsolation(t *testing.T) { } } ctx := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "issuer", Subject: "alice", GrantType: session.GrantTypeUser}) - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/harness_context_regression_test.go b/internal/app/harness_context_regression_test.go index 6e6d5b2040..d0e6c32b6e 100644 --- a/internal/app/harness_context_regression_test.go +++ b/internal/app/harness_context_regression_test.go @@ -102,7 +102,8 @@ func TestDefaultHarnessInstructionsFlowToChildren(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSessionWithProfile(t.Context(), session.ModeDefault, session.Limits{}, server.ProviderSelector{}, tc.profile) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := built.Service.CreateSessionWithProfile(t.Context(), "", session.Limits{}, server.ProviderSelector{}, tc.profile) if err != nil { t.Fatal(err) } diff --git a/internal/app/learned_skills_composition_test.go b/internal/app/learned_skills_composition_test.go index 647d3bad81..15b971f961 100644 --- a/internal/app/learned_skills_composition_test.go +++ b/internal/app/learned_skills_composition_test.go @@ -35,7 +35,8 @@ func TestBuildOwnerlessSessionHydratesLearnedSkillIntoTool(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := built.Service.CreateSession(context.Background(), "", session.Limits{}) if err != nil { t.Fatal(err) } @@ -70,7 +71,8 @@ func TestBuildRestartHydratesCallerBoundLearnedSkillIntoListAndTool(t *testing.T if err != nil { t.Fatal(err) } - sess, err := built1.Service.CreateSession(aliceCtx, session.ModeDefault, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := built1.Service.CreateSession(aliceCtx, "", session.Limits{}) if err != nil { built1.Close() t.Fatal(err) @@ -137,11 +139,12 @@ func TestReplicaHydrationConvergesAcrossReplacementAndRollback(t *testing.T) { t.Fatal(err) } defer replicaB.Close() - aliceSession, err := replicaB.Service.CreateSession(aliceCtx, session.ModeDefault, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + aliceSession, err := replicaB.Service.CreateSession(aliceCtx, "", session.Limits{}) if err != nil { t.Fatal(err) } - bobSession, err := replicaB.Service.CreateSession(bobCtx, session.ModeDefault, session.Limits{}) + bobSession, err := replicaB.Service.CreateSession(bobCtx, "", session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/mcp_broker_authorization_vertical_test.go b/internal/app/mcp_broker_authorization_vertical_test.go index dd38cf2ba1..2fd970723e 100644 --- a/internal/app/mcp_broker_authorization_vertical_test.go +++ b/internal/app/mcp_broker_authorization_vertical_test.go @@ -119,7 +119,7 @@ func TestSessionMCPAuthorization_GrantRegressionParksAndResumes(t *testing.T) { owner := &session.Principal{Issuer: "https://identity.example", Subject: "alice", GrantType: session.GrantTypeUser} ownerCtx := session.WithPrincipal(ctx, owner) intruderCtx := session.WithPrincipal(ctx, &session.Principal{Issuer: owner.Issuer, Subject: "mallory", GrantType: session.GrantTypeUser}) - sess, err := built.Service.CreateSession(ownerCtx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ownerCtx, "", session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/microvm_harness_context_test.go b/internal/app/microvm_harness_context_test.go index 160dd03ce9..65a5863e26 100644 --- a/internal/app/microvm_harness_context_test.go +++ b/internal/app/microvm_harness_context_test.go @@ -439,7 +439,8 @@ func TestMicroVMSuccessorRetainsPlacementAndContext(t *testing.T) { t.Fatal(err) } defer built.Close() - parent, err := built.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + parent, err := built.Service.CreateSession(t.Context(), "", session.Limits{}) if err != nil { t.Fatal(err) } @@ -612,7 +613,8 @@ func TestMicroVMSelectedContextFreshnessAndReadEvidence(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := built.Service.CreateSession(t.Context(), "", session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/microvm_lifecycle_e2e_test.go b/internal/app/microvm_lifecycle_e2e_test.go index d61b497c3c..8683313bd5 100644 --- a/internal/app/microvm_lifecycle_e2e_test.go +++ b/internal/app/microvm_lifecycle_e2e_test.go @@ -495,7 +495,7 @@ func TestMicroVMDefaultPlacementRetainsOneExactAttachmentUntilCloseSession(t *te } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -566,11 +566,11 @@ harness_context: } defer built.Close() - first, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + first, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } - second, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + second, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } @@ -675,7 +675,7 @@ func TestMicroVMOperatorJourneyIsLazyIsolatedAndRestartExact(t *testing.T) { t.Fatalf("composition allocated a microVM: readiness=%d create=%d", manager.calls, daemon.operationCount("create")) } - noFS, err := first.Service.CreateSessionWithProfile(ctx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileNoFS) + noFS, err := first.Service.CreateSessionWithProfile(ctx, "", session.Limits{}, server.ProviderSelector{}, server.ProfileNoFS) if err != nil { first.Close() t.Fatalf("create no-fs session: %v", err) @@ -685,12 +685,12 @@ func TestMicroVMOperatorJourneyIsLazyIsolatedAndRestartExact(t *testing.T) { t.Fatalf("no-fs touched microVM state: ref=%+v readiness=%d create=%d", noFS.EnvironmentRef, manager.calls, daemon.operationCount("create")) } - one, err := first.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + one, err := first.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { first.Close() t.Fatalf("create first default session: %v", err) } - two, err := first.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + two, err := first.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { first.Close() t.Fatalf("create second default session: %v", err) @@ -831,7 +831,7 @@ func TestMicroVMScheduledPlacementSurvivesFiresRestartAndDeletion(t *testing.T) mockllm.ToolCallTurn(session.NewToolCall("write-first", "Shell", json.RawMessage(`{"command":"printf first > shared.txt"}`))), mockllm.TextTurn("first fire complete"), )) - origin, err := first.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + origin, err := first.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { first.Close() t.Fatal(err) diff --git a/internal/app/multiprovider_e2e_test.go b/internal/app/multiprovider_e2e_test.go index 799b794e2f..d695a77ce0 100644 --- a/internal/app/multiprovider_e2e_test.go +++ b/internal/app/multiprovider_e2e_test.go @@ -120,14 +120,14 @@ func TestMultiProviderE2E(t *testing.T) { } // An unknown provider still ⇒ InvalidArgument (never a silent fallback). - _, err = svc.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + _, err = svc.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: "does-not-exist"}) if !errors.Is(err, server.ErrInvalidArgument) { t.Fatalf("unknown-provider create error = %v, want ErrInvalidArgument", err) } // (5) zero selector ⇒ the shared default-provider engine (openai is the default). - zeroSess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + zeroSess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession(zero): %v", err) } @@ -183,7 +183,7 @@ func TestMultiProviderCapabilityEcho(t *testing.T) { // (REPLY-FROM-openrouter) AND that session's caps reflect openrouter's intersected // caps (Image:true), in ONE test. imgModel, _ := firstImageModel(t, providerOpenRouter) - orSess, err := svc.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + orSess, err := svc.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenRouter, ModelID: imgModel}) if err != nil { t.Fatalf("create openrouter session: %v", err) @@ -203,7 +203,7 @@ func TestMultiProviderCapabilityEcho(t *testing.T) { // intersection is false, it DIFFERS from the openrouter echo (per-session), AND the // turn routes to the openai-bound provider — proving routing and caps agree on the // SAME provider per session. - oaSess, err := svc.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + oaSess, err := svc.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenAI, ModelID: imgModel}) if err != nil { t.Fatalf("create openai session: %v", err) @@ -221,7 +221,7 @@ func TestMultiProviderCapabilityEcho(t *testing.T) { // (5) zero-selector session ⇒ echo == DefaultCapabilities (the default provider's // intersected caps). The default is openai (Image:false) on the empty model. - zeroSess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + zeroSess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("create zero-selector session: %v", err) } @@ -272,7 +272,7 @@ func TestMultiProviderResolvedModelEcho(t *testing.T) { // (a) zero-selector default session ⇒ DefaultResolvedModel: the default provider // (openai) + the resolved cfg.Model ("gpt-5"), echoed verbatim — NOT the empty // request model_id. The context window is the catalog's gpt-5 limit (>0). - zeroSess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + zeroSess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession(zero): %v", err) } @@ -288,7 +288,7 @@ func TestMultiProviderResolvedModelEcho(t *testing.T) { // model), not the default and not a naive read-back. Use a real catalogued model // so the window resolves from the catalog. orModel, _ := firstImageModel(t, providerOpenRouter) - orSess, err := svc.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + orSess, err := svc.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenRouter, ModelID: orModel}) if err != nil { t.Fatalf("CreateSessionWithProvider(openrouter): %v", err) @@ -339,7 +339,7 @@ func TestServerConfiguredDefaultModelEcho(t *testing.T) { defer built.Close() svc := built.Service - sess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession(zero-selector): %v", err) } @@ -365,7 +365,7 @@ func TestServerConfiguredDefaultModelEcho(t *testing.T) { // default: the echo and the routing both follow the selector (the configured // tier sits BELOW client-side choices in the precedence chain). const selModel = "gpt-5" - selSess, err := svc.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + selSess, err := svc.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenAI, ModelID: selModel}) if err != nil { t.Fatalf("CreateSessionWithProvider(openai selector): %v", err) @@ -415,7 +415,7 @@ func TestResolvedModelMCPOnlySessionMatchesDefaultWindow(t *testing.T) { svc := built.Service // The default-path window (no per-session engine) — the single-source value. - dfltSess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + dfltSess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession(default): %v", err) } @@ -566,7 +566,7 @@ func TestSubAgentPinsAnthropic(t *testing.T) { defer built.Close() svc := built.Service - sess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/openai_codex_composition_test.go b/internal/app/openai_codex_composition_test.go index c824118bfb..2e196073a5 100644 --- a/internal/app/openai_codex_composition_test.go +++ b/internal/app/openai_codex_composition_test.go @@ -139,7 +139,7 @@ func TestOpenAICodexCompositionScenario(t *testing.T) { t.Fatalf("ListModels provider inventory = Codex:%t API-OpenAI:%t, want both independently selectable", sawCodex, sawAPI) } - codexSession, err := built.Service.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + codexSession, err := built.Service.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenAICodex, ModelID: "gpt-5"}) if err != nil { t.Fatalf("create Codex session: %v", err) @@ -159,7 +159,7 @@ func TestOpenAICodexCompositionScenario(t *testing.T) { t.Fatalf("continuation request omitted the real Read result: %s", bodies[1]) } - apiSession, err := built.Service.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + apiSession, err := built.Service.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenAI, ModelID: "gpt-5"}) if err != nil { t.Fatalf("create API OpenAI session: %v", err) @@ -337,7 +337,7 @@ func TestOpenAICodexExplicitSelectorRehydrates(t *testing.T) { if err != nil { t.Fatalf("Build #1: %v", err) } - sess, err := built1.Service.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + sess, err := built1.Service.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenAICodex, ModelID: "gpt-5", ReasoningEffort: "high"}) if err != nil { built1.Close() @@ -382,7 +382,7 @@ func TestZeroSelectorStillFollowsDeploymentDefault(t *testing.T) { if err != nil { t.Fatalf("Build #1: %v", err) } - sess, err := built1.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built1.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { built1.Close() t.Fatalf("CreateSession: %v", err) @@ -463,7 +463,7 @@ func TestOpenAICodexSecretSentinels(t *testing.T) { } addArtifact("provider status", statusJSON) - sess, err := built.Service.CreateSessionWithProvider(ctx, session.ModeDefault, defaultLimits(), + sess, err := built.Service.CreateSessionWithProvider(ctx, "", defaultLimits(), server.ProviderSelector{ProviderID: providerOpenAICodex, ModelID: "gpt-5"}) if err != nil { built.Close() diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 1486990ed1..2d5c828d0c 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -20,29 +20,36 @@ import ( // so no total order over the tokens exists and none may be inferred from their // position in the table. -// PermissionModeToken is one named combination of posture and default session -// mode. +// PermissionModeToken is one named combination of server ceiling and default +// session mode. type PermissionModeToken struct { // Name is the CLI/YAML spelling. Name string - // Posture is the process-wide half, fixed at startup. + // Posture is the process-wide posture tier, used for TrustProject floor and + // for checker/reviewer gating. No longer drives allow-all rule injection + // (that is now mode-driven in Policy.Evaluate). Posture Posture - // SessionMode is the session half: only the default a new session starts in. + // SessionMode is the default mode new sessions start in. SessionMode session.PermissionMode + // MaxMode is the server ceiling: the most-permissive mode sessions on this + // server are allowed to enter. SetMode rejects a mode above this ceiling. + MaxMode session.PermissionMode } -// permissionModeTable is the token contract. Redundant products (an -// accept-edits variant of auto or yolo) are deliberately absent: allow-all -// already permits edits. +// permissionModeTable is the token contract. 5 modes (plan, default, +// accept-edits, auto, yolo). Redundant products (an accept-edits variant of +// auto or yolo) are deliberately absent: allow-all already permits edits. +// trusted and trusted-accept-edits are dropped as modes; project trust is +// raised via --trust-project combined with any mode. var permissionModeTable = []PermissionModeToken{ - {Name: "plan", Posture: PostureStrict, SessionMode: session.ModePlan}, - {Name: "default", Posture: PostureStrict, SessionMode: session.ModeDefault}, - {Name: "accept-edits", Posture: PostureStrict, SessionMode: session.ModeAccept}, - // The three single-word tokens above strict share their posture's name. - {Name: PostureTrusted.String(), Posture: PostureTrusted, SessionMode: session.ModeDefault}, - {Name: "trusted-accept-edits", Posture: PostureTrusted, SessionMode: session.ModeAccept}, - {Name: PostureAuto.String(), Posture: PostureAuto, SessionMode: session.ModeDefault}, - {Name: PostureYolo.String(), Posture: PostureYolo, SessionMode: session.ModeDefault}, + {Name: "plan", Posture: PostureStrict, SessionMode: session.ModePlan, MaxMode: session.ModePlan}, + {Name: "default", Posture: PostureStrict, SessionMode: session.ModeDefault, MaxMode: session.ModeDefault}, + {Name: "accept-edits", Posture: PostureStrict, SessionMode: session.ModeAccept, MaxMode: session.ModeAccept}, + // auto and yolo: sessions start in the named mode. The allow-all and + // loose-substitution behaviors are injected at evaluation time by + // Policy.Evaluate based on the session's current mode, NOT from Posture. + {Name: PostureAuto.String(), Posture: PostureAuto, SessionMode: session.ModeAuto, MaxMode: session.ModeAuto}, + {Name: PostureYolo.String(), Posture: PostureYolo, SessionMode: session.ModeYolo, MaxMode: session.ModeYolo}, } // PermissionModeNames lists the valid tokens in table order, for help text and @@ -87,9 +94,10 @@ func PermissionModeForPair(p Posture, mode session.PermissionMode) (PermissionMo // Precedence: an explicit --permission-mode flag, then the operator-tier // permissionMode: key, then the deprecated surface (--posture/--yolo and the // operator-tier posture: key, handled by foldOperatorPosture). A token writes -// cfg.Posture and cfg.DefaultSessionMode and marks the posture explicit, so the -// deprecated posture: key cannot override it. --trust-project and --yolo still -// fold MAX-tier on top in resolvePosture, exactly as they do over --posture. +// cfg.Posture, cfg.DefaultSessionMode, and cfg.MaxAllowedMode and marks the +// posture explicit, so the deprecated posture: key cannot override it. +// --trust-project and --yolo still fold MAX-tier on top in resolvePosture, +// exactly as they do over --posture. func foldPermissionMode(cfg Config) (Config, error) { raw := "" source := "" @@ -97,8 +105,11 @@ func foldPermissionMode(cfg Config) (Config, error) { case cfg.PermissionModeFlagSet: raw, source = cfg.PermissionMode, "--permission-mode" case cfg.PostureFlagSet: - // An explicit (deprecated) --posture is a CLI flag and out-ranks the - // operator YAML, the rule --posture already follows for posture:. + // Deprecated --posture: set DefaultSessionMode and MaxAllowedMode from the + // resolved posture for backward compat. The posture is already on cfg.Posture + // (set by the cmd layer); foldOperatorPosture would no-op since PostureFlagSet. + cfg.DefaultSessionMode, cfg.MaxAllowedMode = postureToSessionModes(cfg.Posture) + return foldOperatorPosture(cfg), nil default: if res, ok := cfg.permResolver.(*permconfig.Resolver); ok && res != nil { if v := strings.TrimSpace(res.OperatorPermissionMode()); v != "" { @@ -116,26 +127,38 @@ func foldPermissionMode(cfg Config) (Config, error) { cfg.Posture = tok.Posture cfg.PostureFlagSet = true cfg.DefaultSessionMode = tok.SessionMode + cfg.MaxAllowedMode = tok.MaxMode cfg.permissionModeName = tok.Name return cfg, nil } -// checkerRefusal is the allow-all admission gate. A -// posture that waives the built-in mutate-ask floor leaves the guardrails -// checker as the only inspection of tool content, so starting one with no -// checker and no explicit kill-switch is refused. It keys on the RESOLVED -// posture with no exemption for a flag default; shipped defaults declare their -// choice instead. -func checkerRefusal(cfg Config, checkerConfigured bool) error { +// postureToSessionModes maps a Posture to (DefaultSessionMode, MaxAllowedMode) +// for the deprecated --posture flag path, maintaining backward compat. +func postureToSessionModes(p Posture) (session.PermissionMode, session.PermissionMode) { + switch p { + case PostureAuto: + return session.ModeAuto, session.ModeAuto + case PostureYolo: + return session.ModeYolo, session.ModeYolo + default: // PostureStrict, PostureTrusted → default mode + return session.ModeDefault, session.ModeDefault + } +} + +// checkerRefusal WARNs (no longer refuses) when an allow-all mode is configured +// but no guardrails checker is set. In the new architecture the checker +// requirement is enforced at SetMode time (entering ModeAuto requires a checker); +// the startup check is advisory so the operator sees the misconfiguration early. +func checkerRefusal(cfg Config, checkerConfigured bool) { if cfg.Posture < PostureAuto || checkerConfigured || cfg.GuardrailsDisabled { - return nil + return } - msg := fmt.Sprintf("permission mode %q allows every tool without asking, but no guardrails checker is configured, so nothing would inspect tool content. Fix it one of three ways: set a checker with --guardrails-model ; bind the `guardrail` model slot (--model-slot guardrail= or models.slots.guardrail in settings.yaml); or run unsupervised on purpose with --guardrails off", + msg := fmt.Sprintf("permission mode %q: no guardrails checker configured; entering auto mode will be refused at runtime. Fix it by setting a checker with --guardrails-model or binding the guardrail model slot, or run unsupervised with --guardrails off", cfg.resolvedPermissionModeName()) if cfg.Posture >= PostureYolo { msg += ". " + yoloCheckerAdvisoryNote } - return fmt.Errorf("%s", msg) + cfg.diag().Log(context.Background(), port.LevelWarn, msg) } // yoloCheckerAdvisoryNote states what a configured checker does NOT do at the @@ -145,14 +168,13 @@ const yoloCheckerAdvisoryNote = "At yolo a configured checker is observability-o // headlessTrustRefusal is the headless admission gate. // It runs AFTER resolveTrust, so any legitimate trust source satisfies it, and -// applies only to the trust-naming posture: trust is not auto's or yolo's +// applies only to the trust-raising posture: trust is not auto's or yolo's // defining increment, so those WARN instead (narrateWithheldTrust). func headlessTrustRefusal(cfg Config) error { if !cfg.Headless || cfg.Posture != PostureTrusted || cfg.TrustProject { return nil } - return fmt.Errorf("permission mode %q honours this project's instructions and rules, but a headless root never gains project trust from the permission mode and no trust source is present. Fix it one of three ways: pass --trust-project; add this workspace to trustedWorkspaces in your user-global settings.yaml; or choose a mode that does not name project trust, such as default or auto", - cfg.resolvedPermissionModeName()) + return fmt.Errorf("the trust-raising posture requires a trust source on a headless root, but none is present. Fix it one of three ways: pass --trust-project; add this workspace to trustedWorkspaces in your user-global settings.yaml; or choose a mode that does not raise project trust, such as default or auto") } // narrateWithheldTrust WARNs when a headless allow-all root starts without @@ -199,8 +221,8 @@ func checkerState(cfg Config, configured bool) (state, reason string) { return checkerDisabled, "kill-switch (--guardrails off)" case !configured: return checkerDisabled, "no checker configured" - case cfg.Posture >= PostureYolo: - return checkerAdvisory, "demoted by posture yolo" + case cfg.MaxAllowedMode == session.ModeYolo: + return checkerAdvisory, "demoted: yolo mode has no enforcing checker" } specs, _ := effectiveGuardrailSpecs(cfg) if highestSeverityGuardrailMode(specs) == string(modelhook.ModeAdvisory) { @@ -239,9 +261,10 @@ func narratePermissionMode(cfg Config, checkerConfigured bool) { attrs := []any{ "permission_mode", cfg.resolvedPermissionModeName(), "posture", cfg.Posture.String(), - "posture_scope", "process-wide, fixed at startup; cycling the session mode never changes it", + "posture_scope", "process-wide, fixed at startup; sets TrustProject floor and checker/reviewer gating", "session_mode", string(mode), - "session_mode_scope", "default for new sessions; a session may change it", + "session_mode_scope", "default for new sessions; a session may change it up to the server ceiling", + "max_allowed_mode", string(cfg.MaxAllowedMode), "guardrails_checker", checker, "subagent_ask_reviewer", reviewerState(cfg), } @@ -254,7 +277,7 @@ func narratePermissionMode(cfg Config, checkerConfigured bool) { cfg.diag().Log(context.Background(), port.LevelInfo, "permission mode", attrs...) if cfg.Posture == PostureAuto { cfg.diag().Log(context.Background(), port.LevelInfo, - "permission mode auto: subagents KEEP the command-substitution guard the main agent loses, so a subagent's $(...), backtick, or subshell command that cannot be proved read-only is not auto-run. Headless, the subagent ask reviewer adjudicates it instead of denying it (--subagent-ask-reviewer)") + "permission mode auto: subagents KEEP the command-substitution guard the main agent loses at auto mode, so a subagent's $(...), backtick, or subshell command that cannot be proved read-only is not auto-run. Headless, the subagent ask reviewer adjudicates it instead of denying it (--subagent-ask-reviewer)") } } @@ -266,12 +289,13 @@ func isAskReviewerOptOut(s string) bool { // resolveAskReviewerDefault decides whether the headless subagent ask reviewer // is on by default: headless (no human approver), an -// allow-all posture, no explicit reviewer model, and no explicit opt-out. It +// allow-all mode, no explicit reviewer model, and no explicit opt-out. It // resolves its model through the existing ask-reviewer slot with the // parent-model fallback; when neither resolves, behaviour stays today's // denial and a WARN names the fix. func resolveAskReviewerDefault(cfg Config) Config { - if cfg.Interactive || cfg.Posture < PostureAuto || cfg.SubagentAskReviewerModel != "" || cfg.askReviewerOptOut { + isAllowAll := cfg.MaxAllowedMode == session.ModeAuto || cfg.MaxAllowedMode == session.ModeYolo + if cfg.Interactive || !isAllowAll || cfg.SubagentAskReviewerModel != "" || cfg.askReviewerOptOut { return cfg } if _, ok := resolveSlotModel(cfg, slotAskReviewer, cfg.Model); !ok && strings.TrimSpace(cfg.Model) == "" { diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index 373a113682..cc2e2e1c65 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -46,16 +46,14 @@ func TestTokenTableResolvesExactPairs(t *testing.T) { posture Posture mode session.PermissionMode }{ - "plan": {PostureStrict, session.ModePlan}, - "default": {PostureStrict, session.ModeDefault}, - "accept-edits": {PostureStrict, session.ModeAccept}, - "trusted": {PostureTrusted, session.ModeDefault}, - "trusted-accept-edits": {PostureTrusted, session.ModeAccept}, - "auto": {PostureAuto, session.ModeDefault}, - "yolo": {PostureYolo, session.ModeDefault}, + "plan": {PostureStrict, session.ModePlan}, + "default": {PostureStrict, session.ModeDefault}, + "accept-edits": {PostureStrict, session.ModeAccept}, + "auto": {PostureAuto, session.ModeAuto}, + "yolo": {PostureYolo, session.ModeYolo}, } - if got := PermissionModeNames(); len(got) != len(want) { - t.Fatalf("token set = %v, want exactly the %d tokens", got, len(want)) + if got := PermissionModeNames(); len(got) != 5 { + t.Fatalf("token set = %v, want exactly the 5 tokens", got) } for name, pair := range want { tok, err := ParsePermissionMode(name) @@ -91,80 +89,72 @@ func TestTokenTableResolvesExactPairs(t *testing.T) { t.Errorf("unknown-token error must name the valid set; missing %q in %v", name, err) } } - if _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "autonomous", port.NopDiagnostics{})); err == nil || !strings.Contains(err.Error(), "trusted-accept-edits") { + if _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "autonomous", port.NopDiagnostics{})); err == nil || !strings.Contains(err.Error(), "accept-edits") { t.Fatalf("Build with an unknown token must fail naming the valid set; got %v", err) } } func TestTrustedKeepsCurrentMeaning(t *testing.T) { - cfg := permissionModeCfg(t, "trusted", port.NopDiagnostics{}) + // The deprecated --posture trusted still resolves to PostureTrusted. legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, Posture: PostureTrusted, PostureFlagSet: true} - for name, c := range map[string]Config{"token": cfg, "--posture trusted": legacy} { - built, err := buildIsolated(t, context.Background(), c) - if err != nil { - t.Fatalf("%s: Build: %v", name, err) - } - if got := postureEchoFromBuild(t, built); got != "trusted" { - t.Errorf("%s: posture %q, want trusted", name, got) - } - if got := builtDefaultSessionMode(t, built); got != session.ModeDefault { - t.Errorf("%s: session mode %q, want default", name, got) - } - built.Close() - } -} - -func TestTrustedAcceptEditsIsNameable(t *testing.T) { - built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", port.NopDiagnostics{})) + built, err := buildIsolated(t, context.Background(), legacy) if err != nil { - t.Fatalf("Build: %v", err) + t.Fatalf("--posture trusted: Build: %v", err) } defer built.Close() if got := postureEchoFromBuild(t, built); got != "trusted" { - t.Errorf("posture %q, want trusted", got) + t.Errorf("--posture trusted: posture %q, want trusted", got) } - if got := builtDefaultSessionMode(t, built); got != session.ModeAccept { - t.Errorf("session mode %q, want acceptEdits", got) + if got := builtDefaultSessionMode(t, built); got != session.ModeDefault { + t.Errorf("--posture trusted: session mode %q, want default", got) } } + func TestAllowAllTokenRequiresChecker(t *testing.T) { + // The checker gate is now a runtime WARN, not a startup refusal. + // Build succeeds; entering auto mode without a checker is refused at SetMode time. for _, token := range []string{"auto", "yolo"} { - _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) - if err == nil { - t.Fatalf("%s with no checker and no kill-switch must refuse to start", token) + rec := slogdiagBuffer(t) + cfg := permissionModeCfg(t, token, rec.diag) + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("%s with no checker must still start (checker gate is now a WARN): %v", token, err) } - // The deprecated surface reaches the same resolved posture and the same gate. - legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, AllowAllTools: true} - if _, err := buildIsolated(t, context.Background(), legacy); err == nil { - t.Fatal("--yolo with no checker must refuse to start too: the gate keys on the resolved posture") + built.Close() + if !strings.Contains(rec.String(), "no guardrails checker") { + t.Errorf("%s without checker must WARN about missing checker; log:\n%s", token, rec.String()) } - // Either declared choice satisfies it. + // Either declared choice keeps the WARN from appearing. off := permissionModeCfg(t, token, port.NopDiagnostics{}) off.GuardrailsDisabled = true - built, err := buildIsolated(t, context.Background(), off) + built2, err := buildIsolated(t, context.Background(), off) if err != nil { t.Fatalf("%s with --guardrails off must start: %v", token, err) } - built.Close() + built2.Close() checked := permissionModeCfg(t, token, port.NopDiagnostics{}) checked.GuardrailsModel = "mock-checker" - built, err = buildIsolated(t, context.Background(), checked) + built3, err := buildIsolated(t, context.Background(), checked) if err != nil { t.Fatalf("%s with a configured checker must start: %v", token, err) } - built.Close() + built3.Close() } } func TestCheckerRefusalNamesEveryFix(t *testing.T) { - _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "auto", port.NopDiagnostics{})) - if err == nil { - t.Fatal("auto with no checker must refuse") + // Checker absence is now a startup WARN (not a refusal); the WARN must name every fix. + rec := slogdiagBuffer(t) + cfg := permissionModeCfg(t, "auto", rec.diag) + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("auto with no checker must start (WARN only); got error: %v", err) } - for _, want := range []string{`"auto"`, "--guardrails-model", "`guardrail` model slot", "--guardrails off"} { - if !strings.Contains(err.Error(), want) { - t.Errorf("refusal must name %q; got: %v", want, err) + built.Close() + for _, want := range []string{"no guardrails checker", "--guardrails-model", "`guardrail` model slot", "--guardrails off"} { + if !strings.Contains(rec.String(), want) { + t.Errorf("checker-absent WARN must name %q; log:\n%s", want, rec.String()) } } } @@ -172,16 +162,6 @@ func TestCheckerRefusalNamesEveryFix(t *testing.T) { func TestGateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { properties := []string{"pre-tool veto", "approve-once human ask", "fail-closed"} - _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "yolo", port.NopDiagnostics{})) - if err == nil { - t.Fatal("yolo with no checker must refuse") - } - for _, p := range properties { - if !strings.Contains(err.Error(), p) { - t.Errorf("yolo refusal must name %q as a property the checker lacks; got: %v", p, err) - } - } - rec := slogdiagBuffer(t) cfg := permissionModeCfg(t, "yolo", rec.diag) cfg.GuardrailsModel = "mock-checker" @@ -202,7 +182,7 @@ func TestGateFreeTokenStatesCheckerIsAdvisoryOnly(t *testing.T) { } func TestNonAllowAllTokensRequireNoChecker(t *testing.T) { - for _, token := range []string{"plan", "default", "accept-edits", "trusted", "trusted-accept-edits"} { + for _, token := range []string{"plan", "default", "accept-edits"} { built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, token, port.NopDiagnostics{})) if err != nil { t.Fatalf("%s must start with no checker: %v", token, err) @@ -218,7 +198,7 @@ func TestStartupLineNamesCheckerState(t *testing.T) { want string }{ {"enforcing", Config{Posture: PostureAuto, GuardrailsModel: "m"}, "enforcing"}, - {"advisory at yolo", Config{Posture: PostureYolo, GuardrailsModel: "m"}, "advisory"}, + {"advisory at yolo", Config{Posture: PostureYolo, MaxAllowedMode: session.ModeYolo, GuardrailsModel: "m"}, "advisory"}, {"kill-switch", Config{Posture: PostureAuto, GuardrailsDisabled: true}, "disabled"}, {"none at strict", Config{}, "disabled"}, } @@ -252,22 +232,47 @@ func headlessCfg(t *testing.T, token string, diag port.Diagnostics) Config { } func TestHeadlessTrustTokenRefused(t *testing.T) { - for _, token := range []string{"trusted", "trusted-accept-edits"} { - _, err := buildIsolated(t, context.Background(), headlessCfg(t, token, port.NopDiagnostics{})) - if err == nil { - t.Fatalf("%s on a headless root with no trust source must refuse", token) - } - for _, want := range []string{"--trust-project", "trustedWorkspaces", "default or auto"} { - if !strings.Contains(err.Error(), want) { - t.Errorf("%s refusal must name %q; got: %v", token, want, err) - } + // The trust-raising posture (PostureTrusted) on a headless root with no trust + // source is refused. Reachable via the deprecated --posture trusted flag. + withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) + cfg := Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: true, + Posture: PostureTrusted, + PostureFlagSet: true, + Diagnostics: port.NopDiagnostics{}, + } + _, err := buildIsolated(t, context.Background(), cfg) + if err == nil { + t.Fatal("--posture trusted on a headless root with no trust source must refuse") + } + for _, want := range []string{"--trust-project", "trustedWorkspaces", "default or auto"} { + if !strings.Contains(err.Error(), want) { + t.Errorf("refusal must name %q; got: %v", want, err) } } } func TestHeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { + baseHeadlessTrusted := func(t *testing.T) Config { + t.Helper() + withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) + return Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: true, + Posture: PostureTrusted, + PostureFlagSet: true, + Diagnostics: port.NopDiagnostics{}, + } + } t.Run("explicit --trust-project", func(t *testing.T) { - cfg := headlessCfg(t, "trusted", port.NopDiagnostics{}) + cfg := baseHeadlessTrusted(t) cfg.TrustProject = true built, err := buildIsolated(t, context.Background(), cfg) if err != nil { @@ -278,12 +283,19 @@ func TestHeadlessTrustTokenAcceptsEveryTrustSource(t *testing.T) { t.Run("declared trustedWorkspaces", func(t *testing.T) { ws := t.TempDir() withTrustEnv(t, trustSettingsEnv(t.TempDir(), []byte("trustedWorkspaces:\n - "+ws+"\n"))) - cfg := permissionModeCfg(t, "trusted-accept-edits", port.NopDiagnostics{}) - cfg.Headless = true - cfg.Workspace = ws + cfg := Config{ + Workspace: ws, + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: true, + Posture: PostureTrusted, + PostureFlagSet: true, + Diagnostics: port.NopDiagnostics{}, + } built, err := buildIsolated(t, context.Background(), cfg) if err != nil { - t.Fatalf("declared trust must satisfy the gate, because it runs after the trust fold: %v", err) + t.Fatalf("declared trust must satisfy the gate: %v", err) } built.Close() }) @@ -311,7 +323,15 @@ func TestHeadlessAllowAllStartsWithoutTrust(t *testing.T) { func TestInteractiveTrustTokenGrantsTrust(t *testing.T) { withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) rec := slogdiagBuffer(t) - built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted", rec.diag)) + built, err := buildIsolated(t, context.Background(), Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Posture: PostureTrusted, + PostureFlagSet: true, + Diagnostics: rec.diag, + }) if err != nil { t.Fatalf("interactive trusted must start: %v", err) } @@ -359,7 +379,7 @@ func TestHeadlessAllowAllDefaultsReviewerOn(t *testing.T) { } // The model resolves through the existing slot, then the parent model. - cfg := Config{Posture: PostureAuto, Model: "parent-model", Diagnostics: port.NopDiagnostics{}} + cfg := Config{Posture: PostureAuto, MaxAllowedMode: session.ModeAuto, Model: "parent-model", Diagnostics: port.NopDiagnostics{}} cfg = resolveAskReviewerDefault(cfg) if !cfg.askReviewerDefaultOn { t.Fatal("resolveAskReviewerDefault must engage the reviewer") @@ -407,7 +427,7 @@ func TestReviewerDefaultIsOptOutAndNarrated(t *testing.T) { func TestReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { rec := slogdiagBuffer(t) - cfg := resolveAskReviewerDefault(Config{Posture: PostureAuto, Diagnostics: rec.diag}) + cfg := resolveAskReviewerDefault(Config{Posture: PostureAuto, MaxAllowedMode: session.ModeAuto, Diagnostics: rec.diag}) if cfg.askReviewerDefaultOn { t.Fatal("with no resolvable reviewer model the default must stay off") } @@ -421,7 +441,7 @@ func TestReviewerDefaultDegradesToTodayBehaviour(t *testing.T) { func TestReviewerDefaultIsConfinedToHeadlessAllowAll(t *testing.T) { for name, cfg := range map[string]Config{ - "interactive auto": {Posture: PostureAuto, Interactive: true, Model: "m"}, + "interactive auto": {Posture: PostureAuto, MaxAllowedMode: session.ModeAuto, Interactive: true, Model: "m"}, "headless strict": {Posture: PostureStrict, Model: "m"}, "headless trusted": {Posture: PostureTrusted, Model: "m"}, } { @@ -458,20 +478,22 @@ func TestReviewerAndCheckerNarratedSeparately(t *testing.T) { func TestStartupLineReportsTokenBothHalvesCheckerAndReviewer(t *testing.T) { rec := slogdiagBuffer(t) - built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "trusted-accept-edits", rec.diag)) + cfg := permissionModeCfg(t, "auto", rec.diag) + cfg.GuardrailsModel = "mock-checker" + built, err := buildIsolated(t, context.Background(), cfg) if err != nil { t.Fatalf("Build: %v", err) } built.Close() line := rec.lineContaining(`msg="permission mode"`) for _, want := range []string{ - "permission_mode=trusted-accept-edits", - "posture=trusted", - "session_mode=acceptEdits", + "permission_mode=auto", + "posture=auto", + "session_mode=auto", "process-wide", "a session may change it", - "guardrails_checker=disabled", - "subagent_ask_reviewer=off", + "guardrails_checker=enforcing", + "subagent_ask_reviewer=", } { if !strings.Contains(line, want) { t.Errorf("startup line must carry %q; line: %q", want, line) @@ -497,14 +519,14 @@ func TestPermissionModeIsOperatorTierOnly(t *testing.T) { t.Run("CLI tier honoured", func(t *testing.T) { cfg := base(t) - cfg.PermissionConfigs = []string{operatorFile(t, "trusted-accept-edits")} + cfg.PermissionConfigs = []string{operatorFile(t, "accept-edits")} built, err := buildIsolated(t, context.Background(), cfg) if err != nil { t.Fatalf("Build: %v", err) } defer built.Close() - if got := postureEchoFromBuild(t, built); got != "trusted" { - t.Errorf("posture %q, want trusted", got) + if got := postureEchoFromBuild(t, built); got != "strict" { + t.Errorf("posture %q, want strict", got) } if got := builtDefaultSessionMode(t, built); got != session.ModeAccept { t.Errorf("session mode %q, want acceptEdits", got) @@ -527,7 +549,7 @@ func TestPermissionModeIsOperatorTierOnly(t *testing.T) { }) t.Run("explicit flag outranks the key", func(t *testing.T) { cfg := permissionModeCfg(t, "plan", port.NopDiagnostics{}) - cfg.PermissionConfigs = []string{operatorFile(t, "trusted")} + cfg.PermissionConfigs = []string{operatorFile(t, "default")} built, err := buildIsolated(t, context.Background(), cfg) if err != nil { t.Fatalf("Build: %v", err) @@ -573,27 +595,49 @@ func TestPermissionModeIsOperatorTierOnly(t *testing.T) { }) } -// TestInvariant_NoWireOrDomainSurfaceChanged pins that the vocabulary added no -// session-selectable value: the domain keeps its three -// modes with their strings, the proto enum keeps its four values, and an old -// snapshot's mode string still round-trips. `task api:check` covers the engine -// API surface itself. +// TestInvariant_NoWireOrDomainSurfaceChanged pins that: +// - the five session mode wire strings are stable; +// - the proto enum has exactly the six approved values (UNSPECIFIED, DEFAULT, +// PLAN, ACCEPT_EDITS, AUTO, YOLO — AUTO and YOLO added with the unified +// permission-mode architecture, intentional additive wire change); +// - the token table only writes the five known session modes. +// +// `task api:check` covers the engine API surface itself. func TestInvariant_NoWireOrDomainSurfaceChanged(t *testing.T) { - if got := []session.PermissionMode{session.ModeDefault, session.ModePlan, session.ModeAccept}; !slices.Equal(got, []session.PermissionMode{"default", "plan", "acceptEdits"}) { - t.Fatalf("session modes changed: %v", got) + modes := []session.PermissionMode{ + session.ModeDefault, session.ModePlan, session.ModeAccept, + session.ModeAuto, session.ModeYolo, + } + want := []session.PermissionMode{"default", "plan", "acceptEdits", "auto", "yolo"} + if !slices.Equal(modes, want) { + t.Fatalf("session mode wire strings changed: %v", modes) } names := make([]string, 0, len(mecatlv1.PermissionMode_value)) for name := range mecatlv1.PermissionMode_value { names = append(names, name) } slices.Sort(names) - want := []string{"PERMISSION_MODE_ACCEPT_EDITS", "PERMISSION_MODE_DEFAULT", "PERMISSION_MODE_PLAN", "PERMISSION_MODE_UNSPECIFIED"} - if !slices.Equal(names, want) { - t.Fatalf("proto PermissionMode values = %v, want %v", names, want) + // AUTO and YOLO are intentional additive additions (no break: existing clients + // receive unknown enum values and must ignore them per the proto compatibility + // contract; they do not need to send or recognise them to stay correct). + wantProto := []string{ + "PERMISSION_MODE_ACCEPT_EDITS", + "PERMISSION_MODE_AUTO", + "PERMISSION_MODE_DEFAULT", + "PERMISSION_MODE_PLAN", + "PERMISSION_MODE_UNSPECIFIED", + "PERMISSION_MODE_YOLO", + } + if !slices.Equal(names, wantProto) { + t.Fatalf("proto PermissionMode values = %v, want %v", names, wantProto) + } + knownModes := []session.PermissionMode{ + session.ModeDefault, session.ModePlan, session.ModeAccept, + session.ModeAuto, session.ModeYolo, } for _, tok := range permissionModeTable { - if !slices.Contains([]session.PermissionMode{session.ModeDefault, session.ModePlan, session.ModeAccept}, tok.SessionMode) { - t.Errorf("token %s writes a session mode outside the domain's three: %q", tok.Name, tok.SessionMode) + if !slices.Contains(knownModes, tok.SessionMode) { + t.Errorf("token %s writes an unknown session mode %q", tok.Name, tok.SessionMode) } } } diff --git a/internal/app/posture.go b/internal/app/posture.go index a9a3fe2930..9cda90d598 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -13,18 +13,24 @@ import ( // trust/automation ladder that folds the --yolo / --trust-project // switches into ONE ordered tier (strict < trusted < auto < yolo). Like trust.go // it is a pure composition concern — engine/governance stays session-free and -// posture-unaware; posture only COMPOSES the derived knobs (the allow-all rule, -// the evaluator's loose-substitution option, and the root-aware project-trust -// floor) and every decision still goes THROUGH governance.Evaluate, never a bypass. +// posture-unaware; posture only COMPOSES the derived knobs (the root-aware +// project-trust floor and checker/reviewer gating) and every decision still goes +// THROUGH governance.Evaluate, never a bypass. // // The ladder (owner-approved), and the knobs each tier derives in applyPosture: // -// posture | AllowAllTools | main loose-subst | child loose-subst | TrustProject floor -// --------|---------------|------------------|----------------------|------------------- -// strict | false | false | false | (trust sources only) -// trusted | false | false | false | interactive-only -// auto | true | true | false (child def ON) | interactive-only -// yolo | true | true | TRUE (child def OFF)| interactive-only +// posture | TrustProject floor | DefaultSessionMode (via postureToSessionModes) +// --------|---------------------------|--------------------------------------------- +// strict | (trust sources only) | default +// trusted | interactive-only | default +// auto | interactive-only | auto (allow-all via ModeAuto at eval time) +// yolo | interactive-only | yolo (allow-all + loose-subst at eval time) +// +// Allow-all and loose-substitution are now mode-driven: Policy.Evaluate injects +// allowAllCLIRules() for ModeAuto/ModeYolo and selects the loose evaluator for +// ModeYolo, at call time. Switching a session from yolo→default actually removes +// the allow-all floor. AllowAllTools and LooseChildSubstitution in Config are kept +// for backward compat with test fixtures but no longer drive rule injection. // // Issue #359. TrustProject is the ONE effective positive workspace-trust // decision after resolveTrust. It gates project-tier ingestion through the named @@ -37,13 +43,6 @@ import ( // repo gets neither steering nor a read-only child shell, while every legitimate // trust source admits both. // -// "child loose-subst" is the NEW Config.LooseChildSubstitution: under yolo a -// child/subagent/branch engine ALSO loosens the built-in substitution Ask floor -// (so a $()/backtick/heredoc command auto-runs), turning OFF the child -// prompt-injection defense — the deliberate behaviour change yolo now carries. -// strict/trusted/auto keep that defense ON (childEvaluatorOptions omits -// WithLooseSubstitution), so only yolo lets a child auto-run a substitution. -// // PostureStrict is iota-zero by design: a zero/unrecognised value fails CLOSED to // the safest tier, the structural backstop that mirrors the rest of the harness's // fail-closed posture (an unknown --posture WARNs and lands here, never refusing @@ -206,19 +205,20 @@ func resolvePosture(cfg Config, ceiling Posture) Posture { return resolved } -// applyPosture maps the resolved tier to the derived composition knobs per the -// ladder table: AllowAllTools (the allow-all rule, main + children), -// LooseChildSubstitution (child substitution loosening, yolo only), and the -// project-trust floor. The floor is raised for trusted/auto/yolo on INTERACTIVE -// roots only; a HEADLESS root's ladder never raises TrustProject. Explicit trust -// survives because this function only raises. It MUST run BEFORE resolveTrust so -// the trust fold and permission resolver see the posture-derived interactive -// floor. +// applyPosture maps the resolved tier to the project-trust floor. The floor is +// raised for trusted/auto/yolo on INTERACTIVE roots only; a HEADLESS root's +// ladder never raises TrustProject. Explicit trust survives because this +// function only raises. It MUST run BEFORE resolveTrust so the trust fold and +// permission resolver see the posture-derived interactive floor. +// +// Allow-all and loose-substitution are no longer derived here: they are +// mode-driven (Policy.Evaluate injects allowAllCLIRules for ModeAuto/ModeYolo +// at call time). DefaultSessionMode and MaxAllowedMode are set by foldPermissionMode +// (for explicit token/posture flags) or by the backward-compat fallback in Build() +// (for the deprecated --yolo alias path). func applyPosture(cfg Config) Config { switch cfg.Posture { case PostureYolo: - cfg.AllowAllTools = true - cfg.LooseChildSubstitution = true // TrustProject floor: INTERACTIVE-only. On a HEADLESS root the ladder does // NOT raise TrustProject — the fail-safe default (an untrusted clone gets no // ingestion and no subagent shell without an explicit --trust-project). @@ -226,8 +226,6 @@ func applyPosture(cfg Config) Config { cfg.TrustProject = true } case PostureAuto: - cfg.AllowAllTools = true - cfg.LooseChildSubstitution = false if !cfg.Headless { cfg.TrustProject = true } @@ -291,12 +289,11 @@ func ResolveAuthoritativePosture(cfg Config) Posture { // resolveTrust, so it cannot contradict the following workspace-trust narration. // It is the sole observation/debug surface for the resolved posture + per-defence // state; there is no separate print-and-exit CLI. +// Allow-all and loose-substitution are now mode-driven (not posture-derived), +// so they are not included here. func narratePosture(diag port.Diagnostics, p Posture, trustProject bool) { diag.Log(context.Background(), port.LevelInfo, "operator posture", "posture", p.String(), - "allow_all", p >= PostureAuto, - "main_loose_substitution", p >= PostureAuto, - "child_loose_substitution", p == PostureYolo, "project_ingestion", trustProject, "trust_project", trustProject) } diff --git a/internal/app/posture_build_test.go b/internal/app/posture_build_test.go index 12ec1b02b1..e378bff6cd 100644 --- a/internal/app/posture_build_test.go +++ b/internal/app/posture_build_test.go @@ -39,7 +39,7 @@ func postureEchoFromBuild(t *testing.T, built *Built) string { // silently disconnect, and the input to the #1 security fix. // // (a) operator-tier `posture: auto` → echoed posture "auto" AND the narrated -// composition fact reports allow_all=true (applyPosture derived the knob in Build). +// composition fact reports trust_project= (the posture ladder set it in Build). // (b) a PROJECT-tier `posture: yolo` fixture is IGNORED → echoed posture stays "strict". // (c) user-global `posture: yolo` + a PRIVILEGED Config → Build REFUSES (the // operator-YAML tier cannot escape the root/no-sandbox refusal). @@ -68,8 +68,8 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { if fact == "" { t.Fatalf("expected the narratePosture composition fact; log:\n%s", diag.String()) } - if !strings.Contains(fact, "allow_all=true") { - t.Fatalf("auto must derive allow_all=true in Build; fact: %q", fact) + if !strings.Contains(fact, "trust_project=") { + t.Fatalf("auto posture must narrate trust_project in Build; fact: %q", fact) } }) diff --git a/internal/app/posture_test.go b/internal/app/posture_test.go index 591474e15a..1c1c3324dc 100644 --- a/internal/app/posture_test.go +++ b/internal/app/posture_test.go @@ -80,64 +80,58 @@ func TestPostureConflictWarnFires(t *testing.T) { // TestPostureResolutionTable is the structural anti-drift guard for the // root-aware ladder. TrustProject is both the ingestion decision (through the -// named seam) and the read-only child-shell gate. +// named seam) and the read-only child-shell gate. Allow-all and loose-child +// substitution are now mode-driven (Policy.Evaluate, not applyPosture), so only +// the TrustProject ladder is tested here. func TestPostureResolutionTable(t *testing.T) { for _, root := range []struct { name string headless bool cases []struct { - name string - posture Posture - trustFlag bool - allowAll bool - looseChild bool - trusted bool + name string + posture Posture + trustFlag bool + trusted bool } }{ {"headless", true, []struct { - name string - posture Posture - trustFlag, allowAll, looseChild, trusted bool + name string + posture Posture + trustFlag, trusted bool }{ - {"strict+no-trust", PostureStrict, false, false, false, false}, - {"strict+trust", PostureStrict, true, false, false, true}, - {"trusted+no-trust", PostureTrusted, false, false, false, false}, - {"trusted+trust", PostureTrusted, true, false, false, true}, - {"auto+no-trust", PostureAuto, false, true, false, false}, - {"auto+trust", PostureAuto, true, true, false, true}, - {"yolo+no-trust", PostureYolo, false, true, true, false}, - {"yolo+trust", PostureYolo, true, true, true, true}, + {"strict+no-trust", PostureStrict, false, false}, + {"strict+trust", PostureStrict, true, true}, + {"trusted+no-trust", PostureTrusted, false, false}, + {"trusted+trust", PostureTrusted, true, true}, + {"auto+no-trust", PostureAuto, false, false}, + {"auto+trust", PostureAuto, true, true}, + {"yolo+no-trust", PostureYolo, false, false}, + {"yolo+trust", PostureYolo, true, true}, }}, {"interactive", false, []struct { - name string - posture Posture - trustFlag, allowAll, looseChild, trusted bool + name string + posture Posture + trustFlag, trusted bool }{ - {"strict+no-trust", PostureStrict, false, false, false, false}, - {"strict+trust", PostureStrict, true, false, false, true}, - {"trusted+no-trust", PostureTrusted, false, false, false, true}, - {"trusted+trust", PostureTrusted, true, false, false, true}, - {"auto+no-trust", PostureAuto, false, true, false, true}, - {"auto+trust", PostureAuto, true, true, false, true}, - {"yolo+no-trust", PostureYolo, false, true, true, true}, - {"yolo+trust", PostureYolo, true, true, true, true}, + {"strict+no-trust", PostureStrict, false, false}, + {"strict+trust", PostureStrict, true, true}, + {"trusted+no-trust", PostureTrusted, false, true}, + {"trusted+trust", PostureTrusted, true, true}, + {"auto+no-trust", PostureAuto, false, true}, + {"auto+trust", PostureAuto, true, true}, + {"yolo+no-trust", PostureYolo, false, true}, + {"yolo+trust", PostureYolo, true, true}, }}, } { t.Run(root.name, func(t *testing.T) { for _, tc := range root.cases { got := applyPosture(Config{Headless: root.headless, Posture: tc.posture, TrustProject: tc.trustFlag}) - if got.AllowAllTools != tc.allowAll || got.LooseChildSubstitution != tc.looseChild || got.TrustProject != tc.trusted { - t.Errorf("%s: got allowAll=%v looseChild=%v trust=%v; want %v %v %v", tc.name, - got.AllowAllTools, got.LooseChildSubstitution, got.TrustProject, - tc.allowAll, tc.looseChild, tc.trusted) + if got.TrustProject != tc.trusted { + t.Errorf("%s: got trust=%v; want %v", tc.name, got.TrustProject, tc.trusted) } if projectIngestionAdmitted(got) != tc.trusted { t.Errorf("%s: ingestion=%v, want %v", tc.name, projectIngestionAdmitted(got), tc.trusted) } - mainLoose := len(mainEvaluatorOptions(got)) > 1 - if mainLoose != tc.allowAll { - t.Errorf("%s: main loose-substitution = %v, want %v", tc.name, mainLoose, tc.allowAll) - } } }) } diff --git a/internal/app/remote_execution_test.go b/internal/app/remote_execution_test.go index 4c0022dbcd..be450faf20 100644 --- a/internal/app/remote_execution_test.go +++ b/internal/app/remote_execution_test.go @@ -59,7 +59,7 @@ func TestRemoteScheduleCatalogAndPromptThroughFactory(t *testing.T) { } defer built.Close() ctx := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "issuer", Subject: "alice", GrantType: session.GrantTypeUser}) - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } @@ -246,7 +246,7 @@ func TestRemoteExecutionPreservesOperatorPermissionsUnderAuto(t *testing.T) { } defer built.Close() ctx := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "issuer", Subject: "alice", GrantType: session.GrantTypeUser}) - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } @@ -364,7 +364,9 @@ func TestRemoteExecutionRealFactoryCarriesPostureAndAttenuatedCatalog(t *testing defer built.Close() principal := &session.Principal{Issuer: "https://issuer.example", Subject: "alice", GrantType: session.GrantTypeUser} ctx := session.WithPrincipal(context.Background(), principal) - sess, err := built.Service.CreateSession(ctx, session.ModeAccept, session.Limits{}) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config), + // so all tool calls are auto-allowed and unsupported remote tools return model-visible errors. + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/router_test.go b/internal/app/router_test.go index 92f5dbbd25..bdc159ead6 100644 --- a/internal/app/router_test.go +++ b/internal/app/router_test.go @@ -472,7 +472,7 @@ func TestRouterRoutesChildToClassifiedModelE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -545,7 +545,7 @@ func TestRouterOffIsByteIdenticalE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -631,7 +631,7 @@ func TestRouterCategorySelectorEmptyReasonReducesOnWireE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/scheduler_fire.go b/internal/app/scheduler_fire.go index d5e7bb7394..4879d7eed2 100644 --- a/internal/app/scheduler_fire.go +++ b/internal/app/scheduler_fire.go @@ -70,13 +70,13 @@ func makeFireFuncWithCancel(svc *server.Service, store port.ScheduleStore, defau // Read-leaning default (decision #3): a schedule that does NOT opt into // mutating (Mutating=false) runs in plan mode (read-only toolset) — the // conservative posture for unattended runs. A schedule that opts into - // mutating (Mutating=true) honors its explicit Mode (or default if unset). + // mutating (Mutating=true) honors its explicit Mode (or the server's + // DefaultMode when unset, which reflects the operator's permission + // configuration — for allow-all deployments this is ModeAuto or ModeYolo). + // Passing "" to CreateSessionWithProfile falls back to s.cfg.DefaultMode. // This is the fire-time enforcement; the create seam (the schedule // manager) additionally rejects Mutating=false with a non-plan Mode at save time. - mode := sched.Spec.Mode - if mode == "" { - mode = session.ModeDefault - } + mode := sched.Spec.Mode // "" means "use server's DefaultMode" if !sched.Spec.Mutating { mode = session.ModePlan } diff --git a/internal/app/server_provider_recovery_composition_test.go b/internal/app/server_provider_recovery_composition_test.go index 141826b8a4..fc6666c555 100644 --- a/internal/app/server_provider_recovery_composition_test.go +++ b/internal/app/server_provider_recovery_composition_test.go @@ -160,7 +160,7 @@ func TestServerProviderRecovery_Scenario2_EffectiveDelayNeverRetriesEarly_Compos if err != nil { t.Fatal(err) } - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatal(err) } @@ -349,7 +349,7 @@ func TestServerProviderRecovery_Scenario1_RootAndDirectWriteChildRecoverBeforeTe t.Fatal(err) } defer built.Close() - parent, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + parent, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatal(err) } diff --git a/internal/app/steer_composition_test.go b/internal/app/steer_composition_test.go index cb29fc28ce..b4c6048d7b 100644 --- a/internal/app/steer_composition_test.go +++ b/internal/app/steer_composition_test.go @@ -120,7 +120,7 @@ func TestSteer_EnabledByDefaultEndToEnd(t *testing.T) { t.Fatal("steer capability = false, want true (DEFAULT ON)") } - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -210,7 +210,7 @@ func TestSteer_DisabledCompositionInert(t *testing.T) { t.Fatal("steer capability = true, want false (DisableSteer)") } - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/subagent_agent_router_test.go b/internal/app/subagent_agent_router_test.go index 08921751a8..3e65e39b57 100644 --- a/internal/app/subagent_agent_router_test.go +++ b/internal/app/subagent_agent_router_test.go @@ -89,7 +89,7 @@ func TestRoutableDefRoutesToClassifiedModelE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -160,7 +160,7 @@ func TestPinnedInheritDefDoesNotRouteE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -233,7 +233,7 @@ func TestRoutableDefHallucinatedCategoryFailSoftE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/subagent_model_default_test.go b/internal/app/subagent_model_default_test.go index be83c6a8fd..77926989a0 100644 --- a/internal/app/subagent_model_default_test.go +++ b/internal/app/subagent_model_default_test.go @@ -615,7 +615,7 @@ func TestSubagentModelRoutesChildToCheapModel(t *testing.T) { defer built.Close() svc := built.Service - sess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/subagent_perm_config_test.go b/internal/app/subagent_perm_config_test.go index 68aa3d724a..bda3722aad 100644 --- a/internal/app/subagent_perm_config_test.go +++ b/internal/app/subagent_perm_config_test.go @@ -214,7 +214,14 @@ permissions: // TestChildPolicyAutoApprovesNonSubstitution; asserted here only to document the // contrast with the still-floored substitution case at auto. func TestAutoTierChildLoosensMutateFloorNotSubstitution(t *testing.T) { - // AUTO tier: allow-all, but the child substitution defense stays ON. + // In the unified permission-mode architecture, allow-all and substitution-loosening + // are mode-driven (Policy.Evaluate), not baked in at policy construction. + // - ModeAuto: allowAllCLIRules injected → mutates Allowed; standard evaluator → + // substitution still Asks (the defense stays ON at auto). + // - ModeYolo: allowAllCLIRules + evalLoose injected → both mutates and substitutions + // Allowed on the MAIN policy. + // - Children in ModeAuto: blanket Allow floor for mutates (no ask-floor to loosen), + // Ask for substitutions (defense stays ON — the load-bearing safety assertion). cfg := Config{Workspace: "", Model: "mock", AllowAllTools: true, LooseChildSubstitution: false} mutateArgs, _ := json.Marshal(map[string]string{"command": "zap -rf build"}) // unknown-verb mutate stand-in mutateCall := session.NewToolCall("c1", "Shell", mutateArgs) @@ -224,19 +231,27 @@ func TestAutoTierChildLoosensMutateFloorNotSubstitution(t *testing.T) { // Mirror buildEngine's main-policy construction (rules + evaluator options + // the build-once resolver — nil here, no config sources). mainPolicy := permpolicy.NewPolicyWithResolver(mainRules(cfg), nil, cfg.permResolver, mainEvaluatorOptions(cfg)...) - if got := mainPolicy.Evaluate(context.Background(), "s1", session.ModeDefault, subCall, nil); got.Decision.Effect != governance.Allow { - t.Fatalf("auto-tier main policy should loosen the substitution floor; got %+v", got) + // ModeAuto: allow-all rules + standard evaluator → plain mutate Allows, substitution Asks. + if got := mainPolicy.Evaluate(context.Background(), "s1", session.ModeAuto, mutateCall, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("auto-tier main policy should Allow a plain mutate; got %+v", got) + } + if got := mainPolicy.Evaluate(context.Background(), "s1", session.ModeAuto, subCall, nil); got.Decision.Effect != governance.Ask { + t.Fatalf("auto-tier main policy must NOT loosen the substitution floor (ModeAuto uses standard evaluator); got %+v", got) + } + // ModeYolo: allow-all rules + evalLoose evaluator → both mutates and substitutions Allowed. + if got := mainPolicy.Evaluate(context.Background(), "s1", session.ModeYolo, subCall, nil); got.Decision.Effect != governance.Allow { + t.Fatalf("yolo-tier main policy should loosen the substitution floor (evalLoose); got %+v", got) } childPolicy := childPermPolicy(cfg) // Plain mutate: the blanket child floor allows it (no mutate-ask floor exists // for a child to loosen) → Allow regardless of tier. - if got := childPolicy.Evaluate(context.Background(), "s1", session.ModeDefault, mutateCall, nil); got.Decision.Effect != governance.Allow { + if got := childPolicy.Evaluate(context.Background(), "s1", session.ModeAuto, mutateCall, nil); got.Decision.Effect != governance.Allow { t.Fatalf("child plain mutate should be Allow (blanket floor); got %+v", got) } // Substitution with a non-read-only inner: at AUTO the child loosening is OFF, so the // child still floors at Ask — the load-bearing safety assertion. - if got := childPolicy.Evaluate(context.Background(), "s1", session.ModeDefault, subCall, nil); got.Decision.Effect != governance.Ask { + if got := childPolicy.Evaluate(context.Background(), "s1", session.ModeAuto, subCall, nil); got.Decision.Effect != governance.Ask { t.Fatalf("auto tier must NOT loosen a CHILD's substitution floor; got %+v", got) } } diff --git a/internal/app/subagent_selector_build_test.go b/internal/app/subagent_selector_build_test.go index c045b3106b..fd15185d05 100644 --- a/internal/app/subagent_selector_build_test.go +++ b/internal/app/subagent_selector_build_test.go @@ -59,7 +59,7 @@ func TestBuildWritableSubagentCrossProviderSelection(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -131,7 +131,7 @@ func TestBuildNoFSSubagentCrossProviderSelection(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSessionWithProfile(ctx, session.ModeDefault, defaultLimits(), server.ProviderSelector{}, server.ProfileNoFS) + sess, err := built.Service.CreateSessionWithProfile(ctx, "", defaultLimits(), server.ProviderSelector{}, server.ProfileNoFS) if err != nil { t.Fatalf("CreateSessionWithProfile(no-fs): %v", err) } diff --git a/internal/app/subagent_writable_agent_router_test.go b/internal/app/subagent_writable_agent_router_test.go index cd5555bdc3..fd6d2a677e 100644 --- a/internal/app/subagent_writable_agent_router_test.go +++ b/internal/app/subagent_writable_agent_router_test.go @@ -80,7 +80,7 @@ func TestWritableRoutableDefFullBuildE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/subprovider_test.go b/internal/app/subprovider_test.go index 58ea7ab0b3..92d5f2b67c 100644 --- a/internal/app/subprovider_test.go +++ b/internal/app/subprovider_test.go @@ -305,7 +305,7 @@ func TestDefaultConfigPolicyEvaluatesWithoutPanic(t *testing.T) { defer built.Close() svc := built.Service - sess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -388,7 +388,7 @@ func TestSubproviderHalfAFullBuildE2E(t *testing.T) { defer built.Close() svc := built.Service - sess, err := svc.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := svc.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/team_parallel_router_test.go b/internal/app/team_parallel_router_test.go index 3ccc58f6be..a958b37c1d 100644 --- a/internal/app/team_parallel_router_test.go +++ b/internal/app/team_parallel_router_test.go @@ -583,7 +583,7 @@ func TestTeamRoutesMembersToCategoryModelsE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -632,7 +632,7 @@ func TestTeamRouterOffByteIdenticalE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -667,7 +667,7 @@ func TestParallelRoutesBranchesToCategoryModelsE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -711,7 +711,7 @@ func TestBuiltCloseReapsPreservedParallelWinner(t *testing.T) { } t.Cleanup(built.Close) - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -777,7 +777,7 @@ func TestParallelRouterOffByteIdenticalE2E(t *testing.T) { } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + sess, err := built.Service.CreateSession(ctx, "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/universal_alias_targets_test.go b/internal/app/universal_alias_targets_test.go index 6808a4c781..1bc5c71064 100644 --- a/internal/app/universal_alias_targets_test.go +++ b/internal/app/universal_alias_targets_test.go @@ -191,7 +191,8 @@ func TestADR_0369_Scenario1_UniversalAliasTargets(t *testing.T) { t.Fatalf("Build pair child default: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(t.Context(), session.ModeDefault, defaultLimits()) + // Pass "" to use the server's DefaultMode (ModeYolo from AllowAllTools=true config). + sess, err := built.Service.CreateSession(t.Context(), "", defaultLimits()) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts index e79d5724ab..0ff52f0350 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("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIpgDChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSMAoJZXhlY3V0aW9uGAwgASgLMh0ubWVjYXRsLnYxLkV4ZWN1dGlvblNlbGVjdGlvbhIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMSHQoVYWdlbnRfZGVmaW5pdGlvbl9uYW1lGA0gASgJSgQIARACSgQICBAJSgQIBhAHUgl3b3Jrc3BhY2VSEXNvdXJjZV9zZXNzaW9uX2lkUgdwcm9maWxlImwKEkV4ZWN1dGlvblNlbGVjdGlvbhImCgRub25lGAEgASgLMhgubWVjYXRsLnYxLkV4ZWN1dGlvbk5vbmUSLgoIdGVtcGxhdGUYAiABKAsyHC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGUiDwoNRXhlY3V0aW9uTm9uZSIxChFFeGVjdXRpb25UZW1wbGF0ZRIKCgJpZBgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCSIfCh1MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdCJtCh5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USLwoFaXRlbXMYASADKAsyIC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGVJbmZvEhoKEmludmVudG9yeV9yZXZpc2lvbhgCIAEoCSK9AgoVRXhlY3V0aW9uVGVtcGxhdGVJbmZvEi4KCHRlbXBsYXRlGAEgASgLMhwubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSFQoNZGlzcGxheV90b2tlbhgEIAEoCRJECgpleHRlbnNpb25zGAUgAygLMjAubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlSW5mby5FeHRlbnNpb25zRW50cnkSIAoYZGVjbGFyZWRfZXhlY3V0aW9uX2ZpbGVzGAYgASgIEh8KF2RlY2xhcmVkX2J1aWx0X2luX3NoZWxsGAcgASgIGjEKD0V4dGVuc2lvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIrEBCg1NY3BTZXJ2ZXJTcGVjEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEgwKBHR5cGUYAyABKAkSDwoHY29tbWFuZBgEIAEoCRI2CgdoZWFkZXJzGAUgAygLMiUubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMuSGVhZGVyc0VudHJ5Gi4KDEhlYWRlcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIisKFEdldFNlcnZlckluZm9SZXF1ZXN0EhMKC3Byb3ZpZGVyX2lkGAEgASgJIm8KFUdldFNlcnZlckluZm9SZXNwb25zZRIQCghidWlsZF9pZBgBIAEoCRIdChVzZXJ2ZXJfaW1wbGVtZW50YXRpb24YAiABKAkSJQodbGxtX3Byb3ZpZGVyX2Rpc3BsYXlfZW5kcG9pbnQYAyABKAkiHQobR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0IowBChxHZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEhEKCWFwaV9tYWpvchgBIAEoBRIzCgxjYXBhYmlsaXRpZXMYAiABKAsyHS5tZWNhdGwudjEuU2VydmVyQ2FwYWJpbGl0aWVzEhAKCGZlYXR1cmVzGAMgAygJEhIKCmRlcGxveW1lbnQYBCABKAkivQUKElNlcnZlckNhcGFiaWxpdGllcxILCgNtY3AYASABKAgSFgoOc2xhc2hfY29tbWFuZHMYAiABKAgSDgoGbWVtb3J5GAMgASgIEg4KBnNraWxscxgEIAEoCBINCgV0ZWFtcxgFIAEoCBINCgVzaGVsbBgGIAEoCBINCgVpbWFnZRgHIAEoCBINCgVhdWRpbxgIIAEoCBIOCgZhZ2VudHMYCSABKAgSDAoEc291bBgKIAEoCBISCgp1c2VyX21vZGVsGAsgASgIEhcKD21vZGVsX3NlbGVjdGlvbhgMIAEoCBIPCgdwb3N0dXJlGA0gASgJEhEKCXdvcmt0cmVlcxgOIAEoCBISCgpzY2hlZHVsaW5nGA8gASgIEhIKCnJlZmxlY3Rpb24YECABKAgSGgoSbGVhcm5pbmdfcHJvcG9zYWxzGBEgASgIEhYKDmxlYXJuZWRfc2tpbGxzGBIgASgIEhcKD3N0b3JhZ2VfY2xlYW51cBgWIAEoCBI4CgxtYW51YWxfZHJlYW0YEyABKAsyIi5tZWNhdGwudjEuTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSFgoOc3RvcmFnZV9oZWFsdGgYFyABKAgSDQoFc3RlZXIYGCABKAgSGQoRbWFudWFsX2NvbXBhY3Rpb24YGSABKAgSFQoNc2Vzc2lvbl9kZWJ1ZxgaIAEoCBIRCglkZWJ1Z19tY3AYGyABKAgSHAoUd29ya3NwYWNlX2Vucm9sbG1lbnQYHCABKAgSHAoUbWNwX2Nvbm5lY3Rvcl9zdGF0dXMYHSABKAgSEwoLbWNwX3JlZnJlc2gYHiABKAgSGwoTZXhlY3V0aW9uX3RlbXBsYXRlcxgfIAEoCEoECBQQFUoECBUQFlIPbGVnYWN5X2Fkb3B0aW9uUhFzdG9yYWdlX21pZ3JhdGlvbiI1Ch9MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkisgEKIExpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1Jlc3BvbnNlEhQKDGF2YWlsYWJpbGl0eRgBIAEoCRIYChBlbnJvbGxtZW50X3N0YXRlGAIgASgJEjEKCmNvbm5lY3RvcnMYAyADKAsyHS5tZWNhdGwudjEuTWNwQ29ubmVjdG9yU3RhdHVzEhgKEHRvdGFsX2Nvbm5lY3RvcnMYBCABKA0SEQoJdHJ1bmNhdGVkGAUgASgIIk8KEk1jcENvbm5lY3RvclN0YXR1cxIMCgRuYW1lGAEgASgJEhcKD2NhdGFsb2d1ZV9zdGF0ZRgCIAEoCRISCgp0b29sX2NvdW50GAMgASgNIogCChVDcmVhdGVTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgDIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEjAKDnJlc29sdmVkX21vZGVsGAQgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSLwoJcGxhY2VtZW50GAUgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEiYKHnJlc29sdmVkX2FnZW50X2RlZmluaXRpb25fbmFtZRgGIAEoCUoECAIQA1IMY2FwYWJpbGl0aWVzIlIKEVBsYWNlbWVudE1ldGFkYXRhEgwKBGtpbmQYASABKAkSDQoFbGFiZWwYAiABKAkSDgoGYnJhbmNoGAMgASgJEhAKCHJldmlzaW9uGAQgASgJImgKDVJlc29sdmVkTW9kZWwSEwoLcHJvdmlkZXJfaWQYASABKAkSEAoIbW9kZWxfaWQYAiABKAkSFgoOY29udGV4dF93aW5kb3cYAyABKAMSGAoQcmVhc29uaW5nX2VmZm9ydBgEIAEoCSJkChNTZXNzaW9uQ2FwYWJpbGl0aWVzEg0KBWltYWdlGAEgASgIEg0KBWF1ZGlvGAIgASgIEhcKD2V4ZWN1dGlvbl9maWxlcxgDIAEoCBIWCg5idWlsdF9pbl9zaGVsbBgEIAEoCCIwChFHZXRTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjkKEkdldFNlc3Npb25SZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iOgobR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiUgoUQWN0aXZpdHlSZXBsYXlTdGF0dXMSEQoJYXZhaWxhYmxlGAEgASgIEhAKCGNvbXBsZXRlGAIgASgIEhUKDWF1dGhvcml0YXRpdmUYAyABKAgi7QEKHEdldFNlc3Npb25UcmFuc2NyaXB0UmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIwCghtZXNzYWdlcxgCIAMoCzIeLm1lY2F0bC52MS5Db252ZXJzYXRpb25NZXNzYWdlEhAKCGNvbXBsZXRlGAMgASgIEjEKCGFjdGl2aXR5GAQgASgLMh8ubWVjYXRsLnYxLkFjdGl2aXR5UmVwbGF5U3RhdHVzEgwKBGtpbmQYBSABKAkSNAoMcmVsYXRpb25zaGlwGAYgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXAiOQoaU3RyZWFtU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI3ChhTdHJlYW1TZXNzaW9uTGl2ZVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJYChlXYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDgoGY3Vyc29yGAIgASgJEg4KBnJ1bl9pZBgDIAEoCSJcChpXYXRjaFNlc3Npb25FdmVudHNSZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudBIOCgZjdXJzb3IYAiABKAkSDQoFcGhhc2UYAyABKAkiOAoTTGlzdFNlc3Npb25zUmVxdWVzdBIRCglwYWdlX3NpemUYASABKAUSDgoGY3Vyc29yGAIgASgJIk4KCVByaW5jaXBhbBIOCgZpc3N1ZXIYASABKAkSDwoHc3ViamVjdBgCIAEoCRISCgpncmFudF90eXBlGAMgASgJEgwKBG5hbWUYBCABKAki/gQKDlNlc3Npb25TdW1tYXJ5EhIKCnNlc3Npb25faWQYASABKAkSGAoQbW9kaWZpZWRfYXRfdW5peBgCIAEoAxINCgVzdGF0ZRgDIAEoCRINCgV0dXJucxgEIAEoBRIQCghtb2RlbF9pZBgFIAEoCRIXCg9jcmVhdGVkX2F0X3VuaXgYBiABKAMSIwoFb3duZXIYCCABKAsyFC5tZWNhdGwudjEuUHJpbmNpcGFsEgwKBGtpbmQYCSABKAkSNAoMcmVsYXRpb25zaGlwGAogASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXASPQoMY2FwYWJpbGl0aWVzGAsgASgLMicubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcmVhc29uX2NvZGUYDCABKAkSLwoJcGxhY2VtZW50GA8gASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBAgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI+Cgt0b2tlbl91c2FnZRgRIAMoCzIpLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeS5Ub2tlblVzYWdlRW50cnkSFgoOYWN0aXZpdHlfc3RhdGUYEiABKAkaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECAcQCEoECA0QDkoECA4QD1IFdGl0bGVSCXdvcmtzcGFjZVIQdGl0bGVfcHJvdmVuYW5jZSLmAQoTU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFwYXJlbnRfc2Vzc2lvbl9pZBgBIAEoCRIPCgdjYWxsX2lkGAIgASgJEhkKDGJyYW5jaF9pbmRleBgDIAEoBUgAiAEBEhUKDXNjaGVkdWxlX25hbWUYBCABKAkSGQoRb3JpZ2luX3Nlc3Npb25faWQYBSABKAkSDwoHdGVhbV9pZBgGIAEoCRITCgttZW1iZXJfbmFtZRgHIAEoCRIfChdkZWJ1Z190YXJnZXRfc2Vzc2lvbl9pZBgIIAEoCUIPCg1fYnJhbmNoX2luZGV4IpICChxTZXNzaW9uSW52ZW50b3J5Q2FwYWJpbGl0aWVzEhMKC3B1YmxpY19jaGF0GAEgASgIEg8KB2luc3BlY3QYAiABKAgSIAoYYXV0aG9yaXRhdGl2ZV90cmFuc2NyaXB0GAMgASgIEhcKD2FjdGl2aXR5X3JlcGxheRgEIAEoCBIPCgdjb3B5X2lkGAUgASgIEhcKD3ZpZXdfdHJhbnNjcmlwdBgGIAEoCBIMCgRmb3JrGAcgASgIEg4KBnJlbmFtZRgIIAEoCBIOCgZkZWxldGUYCSABKAgSOQoHcmVhc29ucxgKIAEoCzIoLm1lY2F0bC52MS5TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucyKdAQodU2Vzc2lvbkludmVudG9yeUFjdGlvblJlYXNvbnMSEwoLcHVibGljX2NoYXQYASABKAkSDwoHaW5zcGVjdBgCIAEoCRIPCgdjb3B5X2lkGAMgASgJEhcKD3ZpZXdfdHJhbnNjcmlwdBgEIAEoCRIMCgRmb3JrGAUgASgJEg4KBnJlbmFtZRgGIAEoCRIOCgZkZWxldGUYByABKAkibQoUTGlzdFNlc3Npb25zUmVzcG9uc2USKwoIc2Vzc2lvbnMYASADKAsyGS5tZWNhdGwudjEuU2Vzc2lvblN1bW1hcnkSEwoLbmV4dF9jdXJzb3IYAiABKAkSEwoLdG90YWxfY291bnQYAyABKAUiGQoXR2V0U3RvcmFnZUhlYWx0aFJlcXVlc3Qi3gEKD1JldGVudGlvblBvbGljeRIcChRtYWluX21heF9hZ2Vfc2Vjb25kcxgBIAEoAxIWCg5tYWluX21heF9jb3VudBgCIAEoBRIdChVjaGlsZF9tYXhfYWdlX3NlY29uZHMYAyABKAMSFwoPY2hpbGRfbWF4X2NvdW50GAQgASgFEiEKGXNjaGVkdWxlZF9tYXhfYWdlX3NlY29uZHMYBSABKAMSGwoTc2NoZWR1bGVkX21heF9jb3VudBgGIAEoBRIdChVzd2VlcF9jYWRlbmNlX3NlY29uZHMYByABKAMiyQcKGEdldFN0b3JhZ2VIZWFsdGhSZXNwb25zZRIRCglhdmFpbGFibGUYASABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAIgASgJEhUKDWN1cnJlbnRfYnl0ZXMYAyABKAMSHwoXY3VycmVudF9ieXRlc19hdmFpbGFibGUYBCABKAgSGQoRcmVjbGFpbWFibGVfYnl0ZXMYBSABKAMSIwobcmVjbGFpbWFibGVfYnl0ZXNfYXZhaWxhYmxlGAYgASgIEhUKDXNlc3Npb25fY291bnQYByABKAMSEgoKZmlsZV9jb3VudBgIIAEoAxIQCgh2MV9jb3VudBgJIAEoAxIQCgh2Ml9jb3VudBgKIAEoAxISCgptYWluX2NvdW50GAsgASgDEhMKC2NoaWxkX2NvdW50GAwgASgDEhcKD3NjaGVkdWxlZF9jb3VudBgNIAEoAxIVCg11bmtub3duX2NvdW50GA4gASgDEhUKDWNvcnJ1cHRfY291bnQYDyABKAMSKgoGcG9saWN5GBAgASgLMhoubWVjYXRsLnYxLlJldGVudGlvblBvbGljeRIXCg9sYXN0X3N3ZWVwX3VuaXgYESABKAMSHAoUbGFzdF9zd2VlcF9hdmFpbGFibGUYEiABKAgSFwoPbmV4dF9zd2VlcF91bml4GBMgASgDEhwKFG5leHRfc3dlZXBfYXZhaWxhYmxlGBQgASgIEhIKCmFjdGl2ZV9qb2IYFSABKAkSFAoMbGFzdF9mYWlsdXJlGBYgASgJEiQKHG93bmVybGVzc19zZXNzaW9uc19hdmFpbGFibGUYFyABKAgSLQolb3duZXJsZXNzX3Nlc3Npb25zX3VuYXZhaWxhYmxlX3JlYXNvbhgYIAEoCRIfChdvd25lcmxlc3Nfc2Vzc2lvbl9jb3VudBgZIAEoAxIdChVvd25lcmxlc3Nfc2Vzc2lvbl9pZHMYGiADKAkSJwofb3duZXJsZXNzX3Nlc3Npb25faWRzX3RydW5jYXRlZBgbIAEoCBIlCh1vd25lcmxlc3Nfc2NoZWR1bGVzX2F2YWlsYWJsZRgcIAEoCBIuCiZvd25lcmxlc3Nfc2NoZWR1bGVzX3VuYXZhaWxhYmxlX3JlYXNvbhgdIAEoCRIgChhvd25lcmxlc3Nfc2NoZWR1bGVfY291bnQYHiABKAMSIAoYb3duZXJsZXNzX3NjaGVkdWxlX25hbWVzGB8gAygJEioKIm93bmVybGVzc19zY2hlZHVsZV9uYW1lc190cnVuY2F0ZWQYICABKAgi2QIKDUNsZWFudXBDb3VudHMSDQoFdG90YWwYASABKAUSNQoHYnlfa2luZBgCIAMoCzIkLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5S2luZEVudHJ5EjcKCGJ5X3N0YXRlGAMgAygLMiUubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlTdGF0ZUVudHJ5EjkKCWJ5X3JlYXNvbhgEIAMoCzImLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5UmVhc29uRW50cnkaLQoLQnlLaW5kRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARouCgxCeVN0YXRlRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARovCg1CeVJlYXNvbkVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEihgEKEENsZWFudXBDYW5kaWRhdGUSEgoKc2Vzc2lvbl9pZBgBIAEoCRIMCgRraW5kGAIgASgJEg0KBXN0YXRlGAMgASgJEg4KBnJlYXNvbhgEIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAUgASgDEhcKD2VzdGltYXRlZF9ieXRlcxgGIAEoAyIqChlQbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0Eg0KBWtpbmRzGAEgAygJItMCChpQbGFuU2Vzc2lvbkNsZWFudXBSZXNwb25zZRIaChJjb25maXJtYXRpb25fdG9rZW4YASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRISCgpnZW5lcmF0aW9uGAQgASgJEhYKDnBvbGljeV92ZXJzaW9uGAUgASgJEi0KCGVsaWdpYmxlGAYgAygLMhsubWVjYXRsLnYxLkNsZWFudXBDYW5kaWRhdGUSKwoJcHJvdGVjdGVkGAcgASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMSFwoPZXN0aW1hdGVkX2J5dGVzGAggASgDEhYKDnBsYW5uZWRfam9iX2lkGAkgASgJEjEKD2VsaWdpYmxlX2NvdW50cxgKIAEoCzIYLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzIkEKGkFwcGx5U2Vzc2lvbkNsZWFudXBSZXF1ZXN0EiMKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCUIHukgEcgIQASI2ChtDYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjYKG0dldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiTQoQQ2xlYW51cEl0ZW1FcnJvchITCgtpdGVtX2hhbmRsZRgBIAEoCRITCgtyZWFzb25fY29kZRgCIAEoCRIPCgdtZXNzYWdlGAMgASgJIqwBCgpDbGVhbnVwSm9iEg4KBmpvYl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIRCglwcm9jZXNzZWQYAyABKAUSDwoHZGVsZXRlZBgEIAEoBRIPCgdza2lwcGVkGAUgASgFEg0KBXN0YWxlGAYgASgFEg4KBmZhaWxlZBgHIAEoBRIrCgZlcnJvcnMYCCADKAsyGy5tZWNhdGwudjEuQ2xlYW51cEl0ZW1FcnJvciJWCg5TZXRNb2RlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEicKBG1vZGUYAiABKA4yGS5tZWNhdGwudjEuUGVybWlzc2lvbk1vZGUiNgoPU2V0TW9kZVJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiIyChNDbG9zZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiFgoUQ2xvc2VTZXNzaW9uUmVzcG9uc2UiSwoUUmVuYW1lU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIWCgV0aXRsZRgCIAEoCUIHukgEcgIQASI8ChVSZW5hbWVTZXNzaW9uUmVzcG9uc2USIwoHc2Vzc2lvbhgBIAEoCzISLm1lY2F0bC52MS5TZXNzaW9uIjMKFERlbGV0ZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiFwoVRGVsZXRlU2Vzc2lvblJlc3BvbnNlIm8KE0NsZWFyU2Vzc2lvblJlcXVlc3QSIgoRc291cmNlX3Nlc3Npb25faWQYASABKAlCB7pIBHICEAESHgoRd29ya3RyZWVfc2VsZWN0b3IYAiABKAlIAIgBAUIUChJfd29ya3RyZWVfc2VsZWN0b3IiWwoUQ2xlYXJTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIvCglwbGFjZW1lbnQYAiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGEivgEKEkZvcmtTZXNzaW9uUmVxdWVzdBIiChFzb3VyY2Vfc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARINCgV0aXRsZRgCIAEoCRIYChByZWFzb25pbmdfZWZmb3J0GAMgASgJEh4KEXdvcmt0cmVlX3NlbGVjdG9yGAQgASgJSACIAQESEwoLcHJvdmlkZXJfaWQYBSABKAkSEAoIbW9kZWxfaWQYBiABKAlCFAoSX3dvcmt0cmVlX3NlbGVjdG9yIloKE0ZvcmtTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIvCglwbGFjZW1lbnQYAiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGEiOwoQQ29udGV4dE9jY3VwYW5jeRIUCgxpbnB1dF90b2tlbnMYASABKAMSEQoJZXN0aW1hdGVkGAIgASgIIqwGCgdTZXNzaW9uEhIKCnNlc3Npb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkSJwoEbW9kZRgDIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIhCgZsaW1pdHMYBSABKAsyES5tZWNhdGwudjEuTGltaXRzEg0KBXR1cm5zGAYgASgFEhIKCnRvb2xfY2FsbHMYByABKAUSFwoPY3JlYXRlZF9hdF91bml4GAggASgDEjAKDnJlc29sdmVkX21vZGVsGAkgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSDAoEa2luZBgOIAEoCRI0CgxyZWxhdGlvbnNoaXAYDyABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFkZWJ1Z19tY3Bfc2VydmVycxgQIAMoCRIXCg9kZWJ1Z19tY3BfdG9vbHMYESADKAkSLwoJcGxhY2VtZW50GBIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBMgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI3Cgt0b2tlbl91c2FnZRgUIAMoCzIiLm1lY2F0bC52MS5TZXNzaW9uLlRva2VuVXNhZ2VFbnRyeRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgVIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEj0KGGxhdGVzdF9jb250ZXh0X29jY3VwYW5jeRgWIAEoCzIbLm1lY2F0bC52MS5Db250ZXh0T2NjdXBhbmN5GkgKD1Rva2VuVXNhZ2VFbnRyeRILCgNrZXkYASABKAkSJAoFdmFsdWUYAiABKAsyFS5tZWNhdGwudjEuVG9rZW5Vc2FnZToCOAFKBAgEEAVKBAgKEAtKBAgLEAxKBAgMEA1KBAgNEA5SCXdvcmtzcGFjZVIFdGl0bGVSDGNhcGFiaWxpdGllc1IQdGl0bGVfcHJvdmVuYW5jZVIaYWRvcHRpb25fc291cmNlX3Nlc3Npb25faWQilQEKDFNlc3Npb25UaXRsZRINCgV0aXRsZRgBIAEoCRISCgpwcm92ZW5hbmNlGAIgASgJEhgKEGdlbmVyYXRpb25fc3RhdGUYAyABKAkSNgoObGF0ZXN0X2F0dGVtcHQYBCABKAsyHi5tZWNhdGwudjEuVGl0bGVBdHRlbXB0U3VtbWFyeRIQCghyZXZpc2lvbhgFIAEoBCI4ChNUaXRsZUF0dGVtcHRTdW1tYXJ5EgoKAmlkGAEgASgJEg8KB291dGNvbWUYAiABKAlKBAgDEAQioQEKClRva2VuVXNhZ2USHwoFdG90YWwYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USMQoGbW9kZWxzGAIgAygLMiEubWVjYXRsLnYxLlRva2VuVXNhZ2UuTW9kZWxzRW50cnkaPwoLTW9kZWxzRW50cnkSCwoDa2V5GAEgASgJEh8KBXZhbHVlGAIgASgLMhAubWVjYXRsLnYxLlVzYWdlOgI4ASLEAgoPQ29udmVyc2VSZXF1ZXN0EiMKBnByb21wdBgBIAEoCzIRLm1lY2F0bC52MS5Qcm9tcHRIABImCgVyZXRyeRgCIAEoCzIVLm1lY2F0bC52MS5SZXRyeVN0YXJ0SAASNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAEi4KDGNhbmNlbF9jaGlsZBgMIAEoCzIWLm1lY2F0bC52MS5DYW5jZWxDaGlsZEgAEiEKBXN0ZWVyGA0gASgLMhAubWVjYXRsLnYxLlN0ZWVySAASLgoMc3RlZXJfY2FuY2VsGA4gASgLMhYubWVjYXRsLnYxLlN0ZWVyQ2FuY2VsSABCBgoEa2luZCIzChBDb252ZXJzZVJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IpwBCgdDb250ZW50EiUKBGtpbmQYASABKA4yFy5tZWNhdGwudjEuQ29udGVudC5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCSI8CgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABIOCgpLSU5EX0lNQUdFEAESDgoKS0lORF9BVURJTxACIpADCgxDb250ZW50QmxvY2sSKgoEa2luZBgBIAEoDjIcLm1lY2F0bC52MS5Db250ZW50QmxvY2suS2luZBIRCgltaW1lX3R5cGUYAiABKAkSDAoEZGF0YRgDIAEoDBILCgN1cmwYBCABKAkSDAoEdGV4dBgFIAEoCRIMCgRuYW1lGAYgASgJEg0KBXRpdGxlGAcgASgJEhMKC2Rlc2NyaXB0aW9uGAggASgJEgwKBHNpemUYCSABKAMSEAoIYXVkaWVuY2UYCiADKAkSEAoIcHJpb3JpdHkYCyABKAESFQoNbGFzdF9tb2RpZmllZBgMIAEoCSKcAQoES2luZBIUChBLSU5EX1VOU1BFQ0lGSUVEEAASDQoJS0lORF9URVhUEAESDgoKS0lORF9JTUFHRRACEg4KCktJTkRfQVVESU8QAxIWChJLSU5EX1JFU09VUkNFX0xJTksQBBIaChZLSU5EX0VNQkVEREVEX1JFU09VUkNFEAUSGwoXS0lORF9TVFJVQ1RVUkVEX0NPTlRFTlQQBiIpCgpSZXRyeVN0YXJ0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEifgoGUHJvbXB0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEdGV4dBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50EiYKHnNlcnZlcl9vd25lZF9wbGFuX2NvbnRpbnVhdGlvbhgEIAEoCCLXAQoOUmVzdW1lQXBwcm92YWwSFwoGYXNrX2lkGAEgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYAyABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMSFwoPZXhwZWN0ZWRfcnVuX2lkGAQgASgJEhEKCXJldmlld19pZBgFIAEoCRI4Cg5ndWFyZHJhaWxfa2luZBgGIAEoDjIgLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbEtpbmRKBAgCEANSBWFsbG93IiEKBkNhbmNlbBIXCg9leHBlY3RlZF9ydW5faWQYASABKAkiKAoLQ2FuY2VsQ2hpbGQSGQoIY2hpbGRfaWQYASABKAlCB7pIBHICEAEiZQoFU3RlZXISDAoEdGV4dBgBIAEoCRISCgptZXNzYWdlX2lkGAIgASgJEiEKBXBhcnRzGAMgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSFwoPZXhwZWN0ZWRfcnVuX2lkGAQgASgJIjoKC1N0ZWVyQ2FuY2VsEhIKCm1lc3NhZ2VfaWQYASABKAkSFwoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJIvYBChRSZXNvbHZlUnVuQXNrUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIXCgZhc2tfaWQYAyABKAlCB7pIBHICEAESOQoHdmVyZGljdBgEIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAxIRCglyZXZpZXdfaWQYBSABKAkSOAoOZ3VhcmRyYWlsX2tpbmQYBiABKA4yIC5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxLaW5kIjcKFVJlc29sdmVSdW5Bc2tSZXNwb25zZRIOCgZydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIqoBChVSZXNvbHZlUGxhbkFza1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESFwoGYXNrX2lkGAMgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYBCABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMiOAoWUmVzb2x2ZVBsYW5Bc2tSZXNwb25zZRIOCgZydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIlEKEENhbmNlbFJ1blJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAEiIwoRQ2FuY2VsUnVuUmVzcG9uc2USDgoGcnVuX2lkGAEgASgJIpACCg9TdGVlclJ1blJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESDAoEdGV4dBgDIAEoCRIrCgVwYXJ0cxgEIAMoCzISLm1lY2F0bC52MS5Db250ZW50Qgi6SAWSAQIQEBIbCgptZXNzYWdlX2lkGAUgASgJQge6SARyAhhAOma6SGMaYQoRc3RlZXJfcnVuLmNvbnRlbnQSI3RleHQgYW5kIHBhcnRzIGNhbm5vdCBib3RoIGJlIGVtcHR5Gid0aGlzLnRleHQgIT0gJycgfHwgc2l6ZSh0aGlzLnBhcnRzKSA+IDAiYAoQU3RlZXJSdW5SZXNwb25zZRIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIOCgZydW5faWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCSJzChVDYW5jZWxSdW5TdGVlclJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESGwoKbWVzc2FnZV9pZBgDIAEoCUIHukgEcgIYQCJmChZDYW5jZWxSdW5TdGVlclJlc3BvbnNlEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEg4KBnJ1bl9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJImgKJkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIQoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCUIHukgEcgIQASI2CidHZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uUmVzcG9uc2USCwoDdXJsGAEgASgJIrQBCh5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkIKH1JlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQiswEKHUNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSGAoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCRI0Cg9yZXN1bWVfYXBwcm92YWwYCiABKAsyGS5tZWNhdGwudjEuUmVzdW1lQXBwcm92YWxIABIjCgZjYW5jZWwYCyABKAsyES5tZWNhdGwudjEuQ2FuY2VsSABCCQoHY29udHJvbCJBCh5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQikAEKDUF1dGhvcml6YXRpb24SGAoQYXV0aG9yaXphdGlvbl9pZBgBIAEoCRIPCgdjYWxsX2lkGAIgASgJEi4KCmV4cGlyZXNfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEg4KBnN0YXR1cxgEIAEoCRIUCgxkaXNwbGF5X25hbWUYBSABKAkiPgoXUGxhbkNvbnRpbnVhdGlvbkZhaWx1cmUSEwoLcGxhbl9ydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIrcHCgVFdmVudBIMCgR0eXBlGAEgASgJEgsKA3NlcRgCIAEoAxIMCgR0dXJuGAMgASgFEgwKBHRleHQYBCABKAkSJgoJdG9vbF9jYWxsGAUgASgLMhMubWVjYXRsLnYxLlRvb2xDYWxsEioKC3Rvb2xfcmVzdWx0GAYgASgLMhUubWVjYXRsLnYxLlRvb2xSZXN1bHQSJQoDYXNrGAcgASgLMhgubWVjYXRsLnYxLlBlcm1pc3Npb25Bc2sSIQoGcmVzdWx0GAggASgLMhEubWVjYXRsLnYxLlJlc3VsdBIkCgh0dXJuX2VuZBgKIAEoCzISLm1lY2F0bC52MS5UdXJuRW5kEh0KBGhvb2sYCyABKAsyDy5tZWNhdGwudjEuSG9vaxIlCghzdWJhZ2VudBgMIAEoCzITLm1lY2F0bC52MS5TdWJhZ2VudBIdCgR0ZWFtGA0gASgLMg8ubWVjYXRsLnYxLlRlYW0SJQoIcGFyYWxsZWwYDiABKAsyEy5tZWNhdGwudjEuUGFyYWxsZWwSLAoIc2NoZWR1bGUYDyABKAsyGi5tZWNhdGwudjEuU2NoZWR1bGVQYXlsb2FkEiUKCGFwcHJvdmFsGBAgASgLMhMubWVjYXRsLnYxLkFwcHJvdmFsEioKC3VzZXJfcHJvbXB0GBEgASgLMhUubWVjYXRsLnYxLlVzZXJQcm9tcHQSOAoSY29tcGFjdGlvbl9hcmNoaXZlGBIgASgLMhwubWVjYXRsLnYxLkNvbXBhY3Rpb25BcmNoaXZlEiMKBXN0ZWVyGBMgASgLMhQubWVjYXRsLnYxLlN0ZWVyRWNobxIqCg1zdGVlcl9vdXRjb21lGBQgASgLMhMubWVjYXRsLnYxLlN0ZWVyQWNrEioKC21vZGVsX3JldHJ5GBUgASgLMhUubWVjYXRsLnYxLk1vZGVsUmV0cnkSDgoGcnVuX2lkGBYgASgJEiYKBXRpdGxlGBcgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRIvCg1hdXRob3JpemF0aW9uGBggASgLMhgubWVjYXRsLnYxLkF1dGhvcml6YXRpb24SMgoPY29udHJvbF9yZWZ1c2VkGBkgASgLMhkubWVjYXRsLnYxLkNvbnRyb2xSZWZ1c2VkEkUKGXBsYW5fY29udGludWF0aW9uX2ZhaWx1cmUYGiABKAsyIi5tZWNhdGwudjEuUGxhbkNvbnRpbnVhdGlvbkZhaWx1cmVKBAgJEApSBXVzYWdlIjIKDkNvbnRyb2xSZWZ1c2VkEg4KBmFza19pZBgBIAEoCRIQCghjYXRlZ29yeRgCIAEoCSJ4CgpNb2RlbFJldHJ5EjYKEXJldHJ5X2Rpc3Bvc2l0aW9uGAEgASgOMhsubWVjYXRsLnYxLlJldHJ5RGlzcG9zaXRpb24SMgoPc3RyZWFtX3Byb2dyZXNzGAIgASgOMhkubWVjYXRsLnYxLlN0cmVhbVByb2dyZXNzIlAKCVN0ZWVyRWNobxIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudCJoCghTdGVlckFjaxIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIMCgR0ZXh0GAIgASgJEhAKCHByb21vdGVkGAMgASgIEhIKCm1lc3NhZ2VfaWQYBCABKAkiLQoMR3VhcmRyYWlsUmVmEgsKA3JlZhgBIAEoCRIQCghjYXRlZ29yeRgCIAEoCSKvAwoPR3VhcmRyYWlsUmV2aWV3EhEKCXJldmlld19pZBgBIAEoCRIkCgNqb2IYAiABKA4yFy5tZWNhdGwudjEuR3VhcmRyYWlsSm9iEjIKCmFzc2Vzc21lbnQYAyABKA4yHi5tZWNhdGwudjEuR3VhcmRyYWlsQXNzZXNzbWVudBIyCgppbnNwZWN0aW9uGAQgASgOMh4ubWVjYXRsLnYxLkd1YXJkcmFpbEluc3BlY3Rpb24SNAoLZGlzcG9zaXRpb24YBSABKA4yHy5tZWNhdGwudjEuR3VhcmRyYWlsRGlzcG9zaXRpb24SEwoLcmVhc29uX2NvZGUYBiABKAkSDwoHcnVsZV9pZBgHIAEoCRITCgtydWxlX29yaWdpbhgIIAEoCRIbChNjaGVja2VyX3Byb3ZpZGVyX2lkGAkgASgJEhgKEGNoZWNrZXJfbW9kZWxfaWQYCiABKAkSKQoIY29uY2VybnMYCyADKAsyFy5tZWNhdGwudjEuR3VhcmRyYWlsUmVmEigKB3NvdXJjZXMYDCADKAsyFy5tZWNhdGwudjEuR3VhcmRyYWlsUmVmIqcBChZHdWFyZHJhaWxBcHByb3ZhbFNjb3BlEhEKCXJldmlld19pZBgBIAEoCRIuCgRraW5kGAIgASgOMiAubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsS2luZBIUCgxncmFudF9kaWdlc3QYAyABKAkSFAoMc2Vzc2lvbl9vbmx5GAQgASgIEhgKEHJlcGVhdF9hdmFpbGFibGUYBSABKAhKBAgGEAciMgocTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJItMBChZHdWFyZHJhaWxDb3ZlcmFnZUVudHJ5EgwKBHRvb2wYASABKAkSDQoFcGhhc2UYAiABKAkSJAoDam9iGAMgASgOMhcubWVjYXRsLnYxLkd1YXJkcmFpbEpvYhIMCgRtb2RlGAQgASgJEg8KB3J1bGVfaWQYBSABKAkSEwoLcnVsZV9vcmlnaW4YBiABKAkSMgoKaW5zcGVjdGlvbhgHIAEoDjIeLm1lY2F0bC52MS5HdWFyZHJhaWxJbnNwZWN0aW9uEg4KBnJlYXNvbhgIIAEoCSKbAQodTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVzcG9uc2USDwoHZW5hYmxlZBgBIAEoCBIbChNjaGVja2VyX3Byb3ZpZGVyX2lkGAIgASgJEhgKEGNoZWNrZXJfbW9kZWxfaWQYAyABKAkSMgoHZW50cmllcxgEIAMoCzIhLm1lY2F0bC52MS5HdWFyZHJhaWxDb3ZlcmFnZUVudHJ5IkgKH0dldEd1YXJkcmFpbFJldmlld0RldGFpbFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIRCglyZXZpZXdfaWQYAiABKAkicwogR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVzcG9uc2USEQoJcmV2aWV3X2lkGAEgASgJEg8KB2NvbmNlcm4YAiABKAkSFgoOc291cmNlX2Rpc3BsYXkYAyABKAkSEwoLbmV4dF9hY3Rpb24YBCABKAkikAEKCEFwcHJvdmFsEg4KBmFza19pZBgBIAEoCRIMCgR0b29sGAMgASgJEg8KB2NhbGxfaWQYBCABKAkSKwoHdmVyZGljdBgGIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3QSDgoGb3JpZ2luGAcgASgJSgQIAhADSgQIBRAGUgxhbGxvd19hbHdheXMiUAoKVXNlclByb21wdBIMCgR0ZXh0GAEgASgJEiEKBXBhcnRzGAIgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSEQoJc3ludGhldGljGAMgASgIIkUKEUNvbXBhY3Rpb25BcmNoaXZlEjAKCHJlcGxhY2VkGAEgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2Ui7wEKE0NvbnZlcnNhdGlvbk1lc3NhZ2USDAoEcm9sZRgBIAEoCRIMCgR0ZXh0GAIgASgJEicKCnRvb2xfY2FsbHMYAyADKAsyEy5tZWNhdGwudjEuVG9vbENhbGwSKgoLdG9vbF9yZXN1bHQYBCABKAsyFS5tZWNhdGwudjEuVG9vbFJlc3VsdBIRCglyZWFzb25pbmcYBSABKAkSFgoOcHJvdmlkZXJfcGhhc2UYBiABKAkSIQoFcGFydHMYByADKAsyEi5tZWNhdGwudjEuQ29udGVudBIZChFyZWFzb25pbmdfaXRlbV9pZBgIIAEoCSJ2Cg9TY2hlZHVsZVBheWxvYWQSFQoNc2NoZWR1bGVfbmFtZRgBIAEoCRIPCgdmaXJlX2lkGAIgASgJEhIKCnNlc3Npb25faWQYAyABKAkSDAoEa2luZBgEIAEoCRIMCgRzdG9wGAUgASgJEgsKA2VychgGIAEoCSKOAQoESG9vaxINCgVwaGFzZRgBIAEoCRIMCgR0b29sGAIgASgJEikKCGRlY2lzaW9uGAMgASgOMhcubWVjYXRsLnYxLkhvb2tEZWNpc2lvbhIPCgdjYWxsX2lkGAQgASgJEi0KCWd1YXJkcmFpbBgFIAEoCzIaLm1lY2F0bC52MS5HdWFyZHJhaWxSZXZpZXciqAIKD1JvdXRpbmdEZWNpc2lvbhIPCgdiYWNrZW5kGAEgASgJEhgKEGNsYXNzaWZpZXJfbW9kZWwYAiABKAkSGgoSY2FuZGlkYXRlX2NhdGVnb3J5GAMgASgJEhcKD2NhbmRpZGF0ZV9tb2RlbBgEIAEoCRIXCgpjb25maWRlbmNlGAUgASgBSACIAQESHwoSbWluaW11bV9jb25maWRlbmNlGAYgASgBSAGIAQESDwoHb3V0Y29tZRgHIAEoCRIaChJjb25zZWN1dGl2ZV9taXNzZXMYCCABKAUSEgoKbWlzc19saW1pdBgJIAEoBRIUCgxicmVha2VyX29wZW4YCiABKAhCDQoLX2NvbmZpZGVuY2VCFQoTX21pbmltdW1fY29uZmlkZW5jZSKKBAoIU3ViYWdlbnQSFgoOcGFyZW50X2NhbGxfaWQYASABKAkSEAoIY2hpbGRfaWQYAiABKAkSDAoEZ29hbBgDIAEoCRIRCgl0b29sX25hbWUYBCABKAkSEAoIaXNfZXJyb3IYBSABKAgSEgoKdG9vbF9jb3VudBgGIAEoBRIfCgV1c2FnZRgHIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIMCgRzdG9wGAggASgJEhMKC2R1cmF0aW9uX21zGAkgASgDEhIKCmJhY2tncm91bmQYCiABKAgSFwoPcm91dGVkX2NhdGVnb3J5GAsgASgJEhQKDHJvdXRlZF9tb2RlbBgMIAEoCRINCgVtb2RlbBgNIAEoCRISCgppbm5lcl9raW5kGA4gASgJEgwKBHRleHQYDyABKAkSDgoGZGV0YWlsGBAgASgJEg0KBWNhdXNlGBEgASgJEhYKDnJvdXRpbmdfcmVhc29uGBIgASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YEyABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBQgASgJEhAKCHByb3ZpZGVyGBUgASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgWIAEoCUITChFfcm91dGluZ19kZWNpc2lvbiKmAgoOVGVhbU1lbWJlclNwZWMSDAoEbmFtZRgBIAEoCRIMCgRyb2xlGAIgASgJEhAKCG11dGF0aW5nGAMgASgIEgwKBGxlYWQYBCABKAgSFwoPcm91dGVkX2NhdGVnb3J5GAUgASgJEhQKDHJvdXRlZF9tb2RlbBgGIAEoCRINCgVtb2RlbBgHIAEoCRIWCg5yb3V0aW5nX3JlYXNvbhgIIAEoCRI5ChByb3V0aW5nX2RlY2lzaW9uGAkgASgLMhoubWVjYXRsLnYxLlJvdXRpbmdEZWNpc2lvbkgAiAEBEhAKCHByb3ZpZGVyGAogASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgLIAEoCUITChFfcm91dGluZ19kZWNpc2lvbiL6AwoEVGVhbRIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIPCgd0ZWFtX2lkGAIgASgJEikKBnJvc3RlchgDIAMoCzIZLm1lY2F0bC52MS5UZWFtTWVtYmVyU3BlYxIOCgZtZW1iZXIYBCABKAkSEgoKaW5uZXJfa2luZBgFIAEoCRIMCgR0ZXh0GAYgASgJEhEKCXRvb2xfbmFtZRgHIAEoCRIOCgZkZXRhaWwYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSDgoGcm91bmRzGAogASgFEgwKBHN0b3AYCyABKAkSHwoFdXNhZ2UYDCABKAsyEC5tZWNhdGwudjEuVXNhZ2USFAoMY29udGV4dF91c2VkGA0gASgDEhYKDmNvbnRleHRfd2luZG93GA4gASgDEiIKBXRhc2tzGA8gAygLMhMubWVjYXRsLnYxLlRlYW1UYXNrEigKCGZpbmRpbmdzGBAgAygLMhYubWVjYXRsLnYxLlRlYW1GaW5kaW5nEjYKDGRpc3Bvc2l0aW9ucxgRIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SGQoRbWVtYmVyX3Nlc3Npb25faWQYEiABKAkSDQoFY2F1c2UYEyABKAkSGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBQgASgJIo4FCghQYXJhbGxlbBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIMCgRraW5kGAIgASgJEgwKBGpvaW4YAyABKAkSFAoMYnJhbmNoX2NvdW50GAQgASgFEhQKDGJyYW5jaF9pbmRleBgFIAEoBRIUCgxicmFuY2hfbGFiZWwYBiABKAkSDAoEZ29hbBgHIAEoCRIRCgl0b29sX25hbWUYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSEgoKdG9vbF9jb3VudBgKIAEoBRIOCgZmYWlsZWQYCyABKAgSDAoEc3RvcBgNIAEoCRIfCgV1c2FnZRgOIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgPIAEoAxIOCgZ3aW5uZXIYECABKAUSEAoIY2hpbGRfaWQYEiABKAkSFwoPcm91dGVkX2NhdGVnb3J5GBMgASgJEhQKDHJvdXRlZF9tb2RlbBgUIAEoCRINCgVtb2RlbBgVIAEoCRISCgppbm5lcl9raW5kGBYgASgJEgwKBHRleHQYFyABKAkSDgoGZGV0YWlsGBggASgJEhYKDnJvdXRpbmdfcmVhc29uGBkgASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YGiABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBsgASgJEhAKCHByb3ZpZGVyGBwgASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgdIAEoCUITChFfcm91dGluZ19kZWNpc2lvbkoECAwQDUoECBEQElIJd29ya3NwYWNlUhB3aW5uZXJfd29ya3NwYWNlIjIKCFRvb2xDYWxsEgoKAmlkGAEgASgJEgwKBG5hbWUYAiABKAkSDAoEYXJncxgDIAEoCSKFAQoKVG9vbFJlc3VsdBIPCgdjYWxsX2lkGAEgASgJEg8KB2NvbnRlbnQYAiABKAkSEAoIaXNfZXJyb3IYAyABKAgSJwoGYmxvY2tzGAQgAygLMhcubWVjYXRsLnYxLkNvbnRlbnRCbG9jaxIaChJzdHJ1Y3R1cmVkX2NvbnRlbnQYBSABKAkiowEKDVBlcm1pc3Npb25Bc2sSDgoGYXNrX2lkGAEgASgJEgwKBHRvb2wYAiABKAkSDAoEYXJncxgDIAEoCRIOCgZyZWFzb24YBCABKAkSNAoJZ3VhcmRyYWlsGAUgASgLMiEubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsU2NvcGUSFAoHY2FsbF9pZBgGIAEoCUgAiAEBQgoKCF9jYWxsX2lkIoUCCgZSZXN1bHQSDAoEc3RvcBgBIAEoCRIMCgR0ZXh0GAIgASgJEh8KBXVzYWdlGAMgASgLMhAubWVjYXRsLnYxLlVzYWdlEg0KBWVycm9yGAQgASgJEjsKEXJldHJ5X2Rpc3Bvc2l0aW9uGAYgASgOMhsubWVjYXRsLnYxLlJldHJ5RGlzcG9zaXRpb25IAIgBARI3Cg9zdHJlYW1fcHJvZ3Jlc3MYByABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3NIAYgBAUIUChJfcmV0cnlfZGlzcG9zaXRpb25CEgoQX3N0cmVhbV9wcm9ncmVzc0oECAUQBlIJcGVybWFuZW50IlIKB1R1cm5FbmQSHwoFdXNhZ2UYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USEwoLZHVyYXRpb25fbXMYAiABKAMSEQoJZXN0aW1hdGVkGAMgASgIIoUBCgVVc2FnZRIUCgxpbnB1dF90b2tlbnMYASABKAMSFQoNb3V0cHV0X3Rva2VucxgCIAEoAxIZChFjYWNoZV9yZWFkX3Rva2VucxgDIAEoAxIaChJjYWNoZV93cml0ZV90b2tlbnMYBCABKAMSGAoQcmVhc29uaW5nX3Rva2VucxgFIAEoAyKQAQoLTWNwUmVzb3VyY2USDgoGc2VydmVyGAEgASgJEgsKA3VyaRgCIAEoCRIMCgRuYW1lGAMgASgJEg0KBXRpdGxlGAQgASgJEhMKC2Rlc2NyaXB0aW9uGAUgASgJEhEKCW1pbWVfdHlwZRgGIAEoCRIMCgRzaXplGAcgASgDEhEKCXJlYWRfb25seRgIIAEoCCIpChdMaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBIOCgZzZXJ2ZXIYASABKAkiRQoYTGlzdE1jcFJlc291cmNlc1Jlc3BvbnNlEikKCXJlc291cmNlcxgBIAMoCzIWLm1lY2F0bC52MS5NY3BSZXNvdXJjZSJRChNNY3BSZXNvdXJjZUNvbnRlbnRzEgsKA3VyaRgBIAEoCRIRCgltaW1lX3R5cGUYAiABKAkSDAoEdGV4dBgDIAEoCRIMCgRibG9iGAQgASgMIkcKFlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QSFwoGc2VydmVyGAEgASgJQge6SARyAhABEhQKA3VyaRgCIAEoCUIHukgEcgIQASJLChdSZWFkTWNwUmVzb3VyY2VSZXNwb25zZRIwCghjb250ZW50cxgBIAMoCzIeLm1lY2F0bC52MS5NY3BSZXNvdXJjZUNvbnRlbnRzIlcKEU1jcFByb21wdEFyZ3VtZW50EgwKBG5hbWUYASABKAkSDQoFdGl0bGUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSEAoIcmVxdWlyZWQYBCABKAgifgoJTWNwUHJvbXB0Eg4KBnNlcnZlchgBIAEoCRIMCgRuYW1lGAIgASgJEg0KBXRpdGxlGAMgASgJEhMKC2Rlc2NyaXB0aW9uGAQgASgJEi8KCWFyZ3VtZW50cxgFIAMoCzIcLm1lY2F0bC52MS5NY3BQcm9tcHRBcmd1bWVudCInChVMaXN0TWNwUHJvbXB0c1JlcXVlc3QSDgoGc2VydmVyGAEgASgJIj8KFkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USJQoHcHJvbXB0cxgBIAMoCzIULm1lY2F0bC52MS5NY3BQcm9tcHQiuQEKE0dldE1jcFByb21wdFJlcXVlc3QSFwoGc2VydmVyGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESQAoJYXJndW1lbnRzGAMgAygLMi0ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QuQXJndW1lbnRzRW50cnkaMAoOQXJndW1lbnRzRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASIuChBNY3BQcm9tcHRNZXNzYWdlEgwKBHJvbGUYASABKAkSDAoEdGV4dBgCIAEoCSJaChRHZXRNY3BQcm9tcHRSZXNwb25zZRITCgtkZXNjcmlwdGlvbhgBIAEoCRItCghtZXNzYWdlcxgCIAMoCzIbLm1lY2F0bC52MS5NY3BQcm9tcHRNZXNzYWdlIkwKDU1jcFNlcnZlckluZm8SDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSEQoJdHJhbnNwb3J0GAMgASgJEg0KBWdyb3VwGAQgASgJIocBCglNY3BTb3VyY2USDAoEbmFtZRgBIAEoCRIMCgRraW5kGAIgASgJEg8KB2VuYWJsZWQYAyABKAgSDQoFZ3JvdXAYBCABKAkSKQoHc2VydmVycxgFIAMoCzIYLm1lY2F0bC52MS5NY3BTZXJ2ZXJJbmZvEhMKC2RpYWdub3N0aWNzGAYgAygJIhcKFUxpc3RNY3BTb3VyY2VzUmVxdWVzdCJ1ChZMaXN0TWNwU291cmNlc1Jlc3BvbnNlEiUKB3NvdXJjZXMYASADKAsyFC5tZWNhdGwudjEuTWNwU291cmNlEhAKCHJldmlzaW9uGAIgASgEEg0KBXN0YWxlGAMgASgIEhMKC3JlY29uY2lsaW5nGAQgASgIIjcKGFJlZnJlc2hNY3BTb3VyY2VzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIj4KGVJlZnJlc2hNY3BTb3VyY2VzUmVzcG9uc2USEAoIcmV2aXNpb24YASABKAQSDwoHY2hhbmdlZBgCIAEoCCIbChlMaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0IiwKGkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEg4KBmdyb3VwcxgBIAMoCSJ0CglBZ2VudEluZm8SDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVtb2RlbBgDIAEoCRINCgV0b29scxgEIAMoCRIXCg9wZXJtaXNzaW9uX21vZGUYBSABKAkSDQoFY29sb3IYBiABKAkiEwoRTGlzdEFnZW50c1JlcXVlc3QiOgoSTGlzdEFnZW50c1Jlc3BvbnNlEiQKBmFnZW50cxgBIAMoCzIULm1lY2F0bC52MS5BZ2VudEluZm8iLAoHQ29tbWFuZBIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIjIKE0xpc3RDb21tYW5kc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI8ChRMaXN0Q29tbWFuZHNSZXNwb25zZRIkCghjb21tYW5kcxgBIAMoCzISLm1lY2F0bC52MS5Db21tYW5kImkKCFdvcmt0cmVlEhAKCHNlbGVjdG9yGAEgASgJEgwKBGtpbmQYAiABKAkSDQoFbGFiZWwYAyABKAkSDgoGYnJhbmNoGAQgASgJEhAKCHJldmlzaW9uGAUgASgJEgwKBGJhcmUYBiABKAgiMwoUTGlzdFdvcmt0cmVlc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI/ChVMaXN0V29ya3RyZWVzUmVzcG9uc2USJgoJd29ya3RyZWVzGAEgAygLMhMubWVjYXRsLnYxLldvcmt0cmVlInAKCVNraWxsSW5mbxIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEhMKC2FnZW50X293bmVkGAMgASgIEhMKC293bmVyX2FnZW50GAQgASgJEhYKDmFjdGl2ZV92ZXJzaW9uGAUgASgJIhMKEUxpc3RTa2lsbHNSZXF1ZXN0IjoKEkxpc3RTa2lsbHNSZXNwb25zZRIkCgZza2lsbHMYASADKAsyFC5tZWNhdGwudjEuU2tpbGxJbmZvIkEKDVNraWxsRmlsZUluZm8SDAoEbmFtZRgBIAEoCRIMCgRzaXplGAIgASgDEhQKDGluc3RydWN0aW9ucxgDIAEoCCIuChVMaXN0U2tpbGxGaWxlc1JlcXVlc3QSFQoEbmFtZRgBIAEoCUIHukgEcgIQASJBChZMaXN0U2tpbGxGaWxlc1Jlc3BvbnNlEicKBWZpbGVzGAEgAygLMhgubWVjYXRsLnYxLlNraWxsRmlsZUluZm8iRAoUUmVhZFNraWxsRmlsZVJlcXVlc3QSFQoEbmFtZRgBIAEoCUIHukgEcgIQARIVCgRmaWxlGAIgASgJQge6SARyAhABIigKFVJlYWRTa2lsbEZpbGVSZXNwb25zZRIPCgdjb250ZW50GAEgASgJIqEBCghTb3VsSW5mbxIPCgdjb250ZW50GAEgASgJEhIKCnNpemVfYnl0ZXMYAiABKAMSDgoGc2hhMjU2GAMgASgJEg8KB3ByZXNlbnQYBCABKAgSLQoKcHJvdmVuYW5jZRgFIAEoDjIZLm1lY2F0bC52MS5Tb3VsUHJvdmVuYW5jZRIPCgd0cnVzdGVkGAYgASgIEg8KB2RyaWZ0ZWQYByABKAgiEAoOR2V0U291bFJlcXVlc3QiNAoPR2V0U291bFJlc3BvbnNlEiEKBHNvdWwYASABKAsyEy5tZWNhdGwudjEuU291bEluZm8iMgoOVXNlck1vZGVsRW50cnkSCwoDa2V5GAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIiIKE0dldFVzZXJNb2RlbFJlcXVlc3QSCwoDa2V5GAEgASgJIpYCChFVc2VyTW9kZWxSZXZpc2lvbhILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSDwoHdmVyc2lvbhgEIAEoCRIOCgZzdGF0dXMYBSABKAkSDgoGd3JpdGVyGAYgASgJEg4KBm9yaWdpbhgHIAEoCRIZChFzb3VyY2Vfc2Vzc2lvbl9pZBgIIAEoCRIaChJzb3VyY2VfcHJvcG9zYWxfaWQYCSABKAkSLgoKdXBkYXRlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBKBAgKEAtSD3NvdXJjZV9ldmVudF9pZFIRc291cmNlX21lc3NhZ2VfaWQiigEKD1VzZXJNb2RlbERldGFpbBItCgdjdXJyZW50GAEgASgLMhwubWVjYXRsLnYxLlVzZXJNb2RlbFJldmlzaW9uEi0KB2hpc3RvcnkYAiADKAsyHC5tZWNhdGwudjEuVXNlck1vZGVsUmV2aXNpb24SGQoRaGlzdG9yeV9hdmFpbGFibGUYAyABKAgikgEKFEdldFVzZXJNb2RlbFJlc3BvbnNlEioKB2VudHJpZXMYASADKAsyGS5tZWNhdGwudjEuVXNlck1vZGVsRW50cnkSEgoKc2l6ZV9ieXRlcxgCIAEoAxIOCgZzaGEyNTYYAyABKAkSKgoGZGV0YWlsGAQgASgLMhoubWVjYXRsLnYxLlVzZXJNb2RlbERldGFpbCKSAQoJTW9kZWxJbmZvEgoKAmlkGAEgASgJEhMKC3Byb3ZpZGVyX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRINCgVpbWFnZRgEIAEoCBIRCglyZWFzb25pbmcYBSABKAgSFQoNY29udGV4dF9saW1pdBgGIAEoAxIVCg1wcm9tcHRfY2FjaGVkGAcgASgIIhMKEUxpc3RNb2RlbHNSZXF1ZXN0IpsBCg5Qcm92aWRlclN0YXR1cxITCgtwcm92aWRlcl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIMCgRoaW50GAMgASgJEiMKG2RlZmF1bHRfbW9kZWxfYXV0b19zZWxlY3RlZBgEIAEoCBITCgttb2RlbF9jb3VudBgFIAEoBRIdChVhdmFpbGFibGVfbm90X2RlZmF1bHQYBiABKAgibgoSTGlzdE1vZGVsc1Jlc3BvbnNlEiQKBm1vZGVscxgBIAMoCzIULm1lY2F0bC52MS5Nb2RlbEluZm8SMgoPcHJvdmlkZXJfc3RhdHVzGAIgAygLMhkubWVjYXRsLnYxLlByb3ZpZGVyU3RhdHVzIkEKFVJlZmxlY3RTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABSgQIAhADUgVhc3luYyK5AQoRUmVmbGVjdGlvblJlY2VpcHQSFQoNcmVmbGVjdGlvbl9pZBgBIAEoCRITCgtkaXNwb3NpdGlvbhgCIAEoCRIOCgZxdWV1ZWQYAyABKAUSEQoJYWJzdGFpbmVkGAQgASgIEg4KBnN0YWdlZBgFIAEoBRIQCghwcm9tb3RlZBgGIAEoBRISCgpjb25mbGljdGVkGAcgASgFEg4KBnJlYXNvbhgIIAEoCRIPCgdtZXNzYWdlGAkgASgJIkcKFlJlZmxlY3RTZXNzaW9uUmVzcG9uc2USLQoHcmVjZWlwdBgBIAEoCzIcLm1lY2F0bC52MS5SZWZsZWN0aW9uUmVjZWlwdCLxAgoPTGVhcm5pbmdBdHRlbXB0EgoKAmlkGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSDwoHb3V0Y29tZRgEIAEoCRIUCgxmYWlsdXJlX2NvZGUYBSABKAkSGgoSYXR0ZW1wdF9nZW5lcmF0aW9uGAYgASgEEhgKEGNsYWltX2dlbmVyYXRpb24YByABKAQSNAoQY2xhaW1fZXhwaXJlc19hdBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGAoQY2hlY2twb2ludF9zdGFnZRgJIAEoCRITCgtwcm9wb3NhbF9pZBgKIAEoCRIQCghza2lsbF9pZBgLIAEoCRIuCgpjcmVhdGVkX2F0GAwgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA0gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIwChlHZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABIkkKGkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0IksKG0xpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBINCgVzdGF0ZRgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUiYQocTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRIsCghhdHRlbXB0cxgBIAMoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQSEwoLbmV4dF9jdXJzb3IYAiABKAkiVgocTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABIkwKHU11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0Il4KHExpc3RMZWFybmluZ1Byb3Bvc2Fsc1JlcXVlc3QSDgoGc3RhdHVzGAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBRIPCgdwcm9qZWN0GAQgASgJIr4BChNMZWFybmluZ0V2aWRlbmNlUmVmEhIKCnNlc3Npb25faWQYASABKAkSDwoHbG9jYXRvchgCIAEoCRIPCgdvcmRpbmFsGAMgASgFEhEKCWV2ZW50X3NlcRgEIAEoAxIUCgx0b29sX2NhbGxfaWQYBSABKAkSDgoGZGlnZXN0GAYgASgJEhEKCWF2YWlsYWJsZRgHIAEoCBIUCgxhdmFpbGFiaWxpdHkYCCABKAkSDwoHcHJldmlldxgJIAEoCSJnChBMZWFybmluZ0RlY2lzaW9uEgwKBGtpbmQYASABKAkSDQoFYWN0b3IYAiABKAkSDgoGcmVhc29uGAMgASgJEiYKAmF0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCJ5ChhMZWFybmluZ1Byb21vdGlvblJlY2VpcHQSEgoKbWVtb3J5X2tleRgBIAEoCRIXCg9wcmV2aW91c19leGlzdHMYAiABKAgSGAoQcHJldmlvdXNfdmVyc2lvbhgDIAEoCRIWCg5yZXN1bHRfdmVyc2lvbhgEIAEoCSKcBAoQTGVhcm5pbmdQcm9wb3NhbBIKCgJpZBgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEg4KBnN0YXR1cxgDIAEoCRIMCgRraW5kGAQgASgJEgsKA2tleRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtkZXNjcmlwdGlvbhgHIAEoCRINCgV0aXRsZRgIIAEoCRIMCgRib2R5GAkgASgJEjAKCGV2aWRlbmNlGAogAygLMh4ubWVjYXRsLnYxLkxlYXJuaW5nRXZpZGVuY2VSZWYSEAoIdHJpZ2dlcnMYCyADKAkSLgoJZGVjaXNpb25zGAwgAygLMhsubWVjYXRsLnYxLkxlYXJuaW5nRGVjaXNpb24SNgoJcHJvbW90aW9uGA0gASgLMiMubWVjYXRsLnYxLkxlYXJuaW5nUHJvbW90aW9uUmVjZWlwdBIuCgpjcmVhdGVkX2F0GA4gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIWCg5wcm9qZWN0X3Njb3BlZBgQIAEoCBIbChNwcm9tb3Rpb25fYXZhaWxhYmxlGBEgASgIEiQKHHByb21vdGlvbl91bmF2YWlsYWJsZV9yZWFzb24YEiABKAkSGAoQbGVhcm5lZF9za2lsbF9pZBgTIAEoCSJkCh1MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRIuCglwcm9wb3NhbHMYASADKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbBITCgtuZXh0X2N1cnNvchgCIAEoCSJCChpHZXRMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAIgASgJIkwKG0dldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsIpMBCh1EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABEhkKCGRlY2lzaW9uGAMgASgJQge6SARyAhABEg4KBnJlYXNvbhgEIAEoCRIPCgdwcm9qZWN0GAUgASgJIk8KHkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsImcKHFVuZG9MZWFybmluZ1Byb21vdGlvblJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAMgASgJIk4KHVVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwi7AMKE0xlYXJuZWRTa2lsbFZlcnNpb24SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIPCgd2ZXJzaW9uGAMgASgJEhAKCHJldmlzaW9uGAQgASgJEg0KBXN0YXRlGAUgASgJEhMKC293bmVyX2FnZW50GAYgASgJEhMKC2Rlc2NyaXB0aW9uGAcgASgJEgwKBGJvZHkYCCABKAkSEgoKc3VwZXJzZWRlcxgJIAEoCRIWCg5ldmlkZW5jZV9jb3VudBgKIAEoBRIwCghldmlkZW5jZRgLIAMoCzIeLm1lY2F0bC52MS5MZWFybmluZ0V2aWRlbmNlUmVmEi8KC2V2YWx1YXRpb25zGAwgAygLMhoubWVjYXRsLnYxLlNraWxsRXZhbHVhdGlvbhIvCghyZWNlaXB0cxgNIAMoCzIdLm1lY2F0bC52MS5Ta2lsbENoYW5nZVJlY2VpcHQSLgoKY3JlYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgilAEKD1NraWxsRXZhbHVhdGlvbhIPCgd2ZXJkaWN0GAEgASgJEhMKC2ZpeHR1cmVfaWRzGAIgAygJEhAKCGJhc2VsaW5lGAMgASgJEhEKCXRyZWF0bWVudBgEIAEoCRIOCgZyZWFzb24YBSABKAkSJgoCYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIoIDChJTa2lsbENoYW5nZVJlY2VpcHQSCgoCaWQYASABKAkSEAoIc2tpbGxfaWQYAiABKAkSDAoEbmFtZRgDIAEoCRIPCgd2ZXJzaW9uGAQgASgJEhEKCW9wZXJhdGlvbhgFIAEoCRISCgpmcm9tX3N0YXRlGAYgASgJEhAKCHRvX3N0YXRlGAcgASgJEhYKDmV2aWRlbmNlX2NvdW50GAggASgFEhoKEnNvdXJjZV9zZXNzaW9uX2lkcxgJIAMoCRIcChRzb3VyY2VfdG9vbF9jYWxsX2lkcxgKIAMoCRIPCgd2ZXJkaWN0GAsgASgJEhMKC2ZpeHR1cmVfaWRzGAwgAygJEhAKCGJhc2VsaW5lGA0gASgJEhEKCXRyZWF0bWVudBgOIAEoCRImCgJhdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgibgoYTGlzdExlYXJuZWRTa2lsbHNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFEg0KBXN0YXRlGAQgASgJEhMKC293bmVyX2FnZW50GAUgASgJIoUBChlMaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlEi4KBnNraWxscxgBIAMoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhMKC25leHRfY3Vyc29yGAIgASgJEhIKCmdlbmVyYXRpb24YAyABKAQSDwoHcHJvamVjdBgEIAEoCSJtChZHZXRMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESDwoHdmVyc2lvbhgEIAEoCSJtChdHZXRMZWFybmVkU2tpbGxSZXNwb25zZRItCgVza2lsbBgBIAEoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCSKhAQofRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEh0KDGZyb21fdmVyc2lvbhgEIAEoCUIHukgEcgIQARIbCgp0b192ZXJzaW9uGAUgASgJQge6SARyAhABIpEBCiBEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRIMCgRkaWZmGAEgASgJEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCRIQCghza2lsbF9pZBgEIAEoCRIUCgxmcm9tX3ZlcnNpb24YBSABKAkSEgoKdG9fdmVyc2lvbhgGIAEoCSKdAQoZTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEhgKB3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEipwEKGk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEi0KBXNraWxsGAEgASgLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJEhoKEnB1YmxpY2F0aW9uX3N0YXR1cxgEIAEoCRIZChFwdWJsaWNhdGlvbl9lcnJvchgFIAEoCSKmAQobUm9sbGJhY2tMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESHwoOdGFyZ2V0X3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEiSQoXTGlzdFNraWxsQ2hhbmdlc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUihAEKGExpc3RTa2lsbENoYW5nZXNSZXNwb25zZRIuCgdjaGFuZ2VzGAEgAygLMh0ubWVjYXRsLnYxLlNraWxsQ2hhbmdlUmVjZWlwdBITCgtuZXh0X2N1cnNvchgCIAEoCRISCgpnZW5lcmF0aW9uGAMgASgEEg8KB3Byb2plY3QYBCABKAkijwEKEUNyZWF0ZVRlYW1SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEbmFtZRgCIAEoCRIoCgdtZW1iZXJzGAMgAygLMhcubWVjYXRsLnYxLlRlYW1tYXRlU3BlYxIMCgRnb2FsGAQgASgJEhcKD21heF90ZWFtX3Rva2VucxgFIAEoBSJNChJDcmVhdGVUZWFtUmVzcG9uc2USDwoHdGVhbV9pZBgBIAEoCRImCgdtZW1iZXJzGAIgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXIicQoMVGVhbW1hdGVTcGVjEhUKBG5hbWUYASABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgCIAEoCRIMCgRsZWFkGAMgASgIEhAKCG11dGF0aW5nGAQgASgIEhYKDmluaXRpYWxfcHJvbXB0GAUgASgJIpMBChRTcGF3blRlYW1tYXRlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgDIAEoCRIMCgRsZWFkGAQgASgIEhAKCG11dGF0aW5nGAUgASgIEhYKDmluaXRpYWxfcHJvbXB0GAYgASgJIj4KFVNwYXduVGVhbW1hdGVSZXNwb25zZRIlCgZtZW1iZXIYASABKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlciJwChpTZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhMKAnRvGAIgASgJQge6SARyAhABEgwKBGZyb20YAyABKAkSFQoEYm9keRgEIAEoCUIHukgEcgIQASIdChtTZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2UiSgoVQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESFwoGbWVtYmVyGAIgASgJQge6SARyAhABIhgKFkNhbmNlbFRlYW1tYXRlUmVzcG9uc2UiKgoOUnVuVGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASJlCglUZWFtRXZlbnQSDgoGbWVtYmVyGAEgASgJEh8KBWV2ZW50GAIgASgLMhAubWVjYXRsLnYxLkV2ZW50EicKB291dGNvbWUYAyABKAsyFi5tZWNhdGwudjEuVGVhbU91dGNvbWUi2wEKC1RlYW1PdXRjb21lEg4KBnJvdW5kcxgBIAEoBRIRCglxdWllc2NlbnQYAiABKAgSGAoQYnVkZ2V0X2V4aGF1c3RlZBgDIAEoCBIMCgRzdG9wGAQgASgJEh8KBXVzYWdlGAUgASgLMhAubWVjYXRsLnYxLlVzYWdlEjYKDGRpc3Bvc2l0aW9ucxgGIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SKAoIZmluZGluZ3MYByADKAsyFi5tZWNhdGwudjEuVGVhbUZpbmRpbmciKwoPTGlzdFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEicQoQTGlzdFRlYW1SZXNwb25zZRImCgdtZW1iZXJzGAEgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXISIgoFdGFza3MYAiADKAsyEy5tZWNhdGwudjEuVGVhbVRhc2sSEQoJcXVpZXNjZW50GAMgASgIIlEKClRlYW1NZW1iZXISDAoEbmFtZRgBIAEoCRISCgphZ2VudF90eXBlGAIgASgJEg0KBXN0YXRlGAMgASgJEhIKCnNlc3Npb25faWQYBCABKAkiWgoIVGVhbVRhc2sSCgoCaWQYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSEAoIYXNzaWduZWUYBCABKAkSDAoEZGVwcxgFIAMoCSIrCgtUZWFtRmluZGluZxIOCgZtZW1iZXIYASABKAkSDAoEYm9keRgCIAEoCSJ9ChVUZWFtTWVtYmVyRGlzcG9zaXRpb24SDAoEbmFtZRgBIAEoCRIPCgdzdG9wcGVkGAIgASgIEi8KBnJlYXNvbhgDIAEoDjIfLm1lY2F0bC52MS5UZWFtTWVtYmVyU3RvcFJlYXNvbhIUCgxlcnJvcl9yb3VuZHMYBCABKAUiLgoSQ2xlYW51cFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEiFQoTQ2xlYW51cFRlYW1SZXNwb25zZSJvChJBcHByb3ZlUGxhblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIuCgt0YXJnZXRfbW9kZRgCIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIMCgRub3RlGAMgASgJIokBChdNYW51YWxEcmVhbUNhcGFiaWxpdGllcxI4Cg5wcm9qZWN0X21lbW9yeRgBIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkSNAoKdXNlcl9tb2RlbBgCIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkiVQoVRHJlYW1UYXJnZXRDYXBhYmlsaXR5EhAKCGdlbmVyYXRlGAEgASgIEg4KBmRlY2lkZRgCIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAyABKAkiKgoYR2VuZXJhdGVEcmVhbVBsYW5SZXF1ZXN0Eg4KBnRhcmdldBgBIAEoCSJFChlHZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlEigKBHBsYW4YASABKAsyGi5tZWNhdGwudjEuRHJlYW1SZXZpZXdQbGFuIjsKFkRlY2lkZURyZWFtUGxhblJlcXVlc3QSDwoHcGxhbl9pZBgBIAEoCRIQCghkZWNpc2lvbhgCIAEoCSJDChdEZWNpZGVEcmVhbVBsYW5SZXNwb25zZRIoCgdyZWNlaXB0GAEgASgLMhcubWVjYXRsLnYxLkRyZWFtUmVjZWlwdCLLAQoPRHJlYW1SZXZpZXdQbGFuEgoKAmlkGAEgASgJEg4KBnRhcmdldBgCIAEoCRIuCgpleHBpcmVzX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIfChdwbGFubmVkX29wZXJhdGlvbl9jb3VudBgEIAEoBRIcChRwbGFubmVkX3NvdXJjZV9jb3VudBgFIAEoBRItCgpvcGVyYXRpb25zGAYgAygLMhkubWVjYXRsLnYxLkRyZWFtT3BlcmF0aW9uIt8BCg5EcmVhbU9wZXJhdGlvbhIMCgRraW5kGAEgASgJEi0KCHN1cnZpdm9yGAIgASgLMhsubWVjYXRsLnYxLkRyZWFtUGFydGljaXBhbnQSLAoHc291cmNlcxgDIAMoCzIbLm1lY2F0bC52MS5EcmVhbVBhcnRpY2lwYW50EjAKC3JlcGxhY2VtZW50GAQgASgLMhsubWVjYXRsLnYxLkRyZWFtUmVwbGFjZW1lbnQSDgoGcmVhc29uGAUgASgJEiAKGGV4YWN0X2R1cGxpY2F0ZV9lbGlnaWJsZRgGIAEoCCJDChBEcmVhbVBhcnRpY2lwYW50EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCSI2ChBEcmVhbVJlcGxhY2VtZW50Eg0KBXZhbHVlGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJItcBCgxEcmVhbVJlY2VpcHQSCgoCaWQYASABKAkSDgoGdGFyZ2V0GAIgASgJEhMKC2Rpc3Bvc2l0aW9uGAMgASgJEhwKFHBsYW5uZWRfc291cmNlX2NvdW50GAQgASgFEhwKFGFwcGxpZWRfc291cmNlX2NvdW50GAUgASgFEh8KF2NvbmZsaWN0ZWRfc291cmNlX2NvdW50GAYgASgFEhwKFHNraXBwZWRfc291cmNlX2NvdW50GAcgASgFEhsKE2ZhaWxlZF9zb3VyY2VfY291bnQYCCABKAUiNAoVQ29tcGFjdFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiKwoWQ29tcGFjdFNlc3Npb25SZXNwb25zZRIRCgljb21wYWN0ZWQYASABKAgiNwohV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkiTgohV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSFQoNZW5yb2xsbWVudF9pZBgCIAEoCSJxChNXb3Jrc3BhY2VFbnJvbGxtZW50EhUKDWVucm9sbG1lbnRfaWQYASABKAkSDgoGc3RhdHVzGAIgASgJEhkKEXJlcXVpcmVkX3NlcnZpY2VzGAMgASgNEhgKEHByZXNlbnRhdGlvbl91cmwYBCABKAkqigEKDlBlcm1pc3Npb25Nb2RlEh8KG1BFUk1JU1NJT05fTU9ERV9VTlNQRUNJRklFRBAAEhsKF1BFUk1JU1NJT05fTU9ERV9ERUZBVUxUEAESGAoUUEVSTUlTU0lPTl9NT0RFX1BMQU4QAhIgChxQRVJNSVNTSU9OX01PREVfQUNDRVBUX0VESVRTEAMqkgEKD0FwcHJvdmFsVmVyZGljdBIgChxBUFBST1ZBTF9WRVJESUNUX1VOU1BFQ0lGSUVEEAASGQoVQVBQUk9WQUxfVkVSRElDVF9ERU5ZEAESHwobQVBQUk9WQUxfVkVSRElDVF9BTExPV19PTkNFEAISIQodQVBQUk9WQUxfVkVSRElDVF9BTExPV19BTFdBWVMQAyq+AQoMU3RlZXJPdXRjb21lEh0KGVNURUVSX09VVENPTUVfVU5TUEVDSUZJRUQQABIaChZTVEVFUl9PVVRDT01FX0FDQ0VQVEVEEAESGgoWU1RFRVJfT1VUQ09NRV9BUFBFTkRFRBACEhsKF1NURUVSX09VVENPTUVfUkVUUkFDVEVEEAMSHgoaU1RFRVJfT1VUQ09NRV9OT05FX1BFTkRJTkcQBBIaChZTVEVFUl9PVVRDT01FX1RPT19MQVRFEAUqgAEKDEd1YXJkcmFpbEpvYhIdChlHVUFSRFJBSUxfSk9CX1VOU1BFQ0lGSUVEEAASGAoUR1VBUkRSQUlMX0pPQl9BQ1RJT04QARIZChVHVUFSRFJBSUxfSk9CX0lOQk9VTkQQAhIcChhHVUFSRFJBSUxfSk9CX1BFUk1JU1NJT04QAyqqAQoTR3VhcmRyYWlsQXNzZXNzbWVudBIkCiBHVUFSRFJBSUxfQVNTRVNTTUVOVF9VTlNQRUNJRklFRBAAEiMKH0dVQVJEUkFJTF9BU1NFU1NNRU5UX0FDQ0VQVEFCTEUQARIjCh9HVUFSRFJBSUxfQVNTRVNTTUVOVF9QUk9ISUJJVEVEEAISIwofR1VBUkRSQUlMX0FTU0VTU01FTlRfVU5SRVNPTFZFRBADKowBChNHdWFyZHJhaWxJbnNwZWN0aW9uEiQKIEdVQVJEUkFJTF9JTlNQRUNUSU9OX1VOU1BFQ0lGSUVEEAASIQodR1VBUkRSQUlMX0lOU1BFQ1RJT05fQ09NUExFVEUQARIsCihHVUFSRFJBSUxfSU5TUEVDVElPTl9PUEVSQVRJT05BTF9GQUlMVVJFEAIq0AIKFEd1YXJkcmFpbERpc3Bvc2l0aW9uEiUKIUdVQVJEUkFJTF9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEiEKHUdVQVJEUkFJTF9ESVNQT1NJVElPTl9FWEVDVVRFEAESJAogR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0FTS19BQ1RJT04QAhIpCiVHVUFSRFJBSUxfRElTUE9TSVRJT05fV0lUSEhPTERfUkVTVUxUEAMSKAokR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1JFTEVBU0VfUkVTVUxUEAQSHgoaR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0RFTlkQBRInCiNHVUFSRFJBSUxfRElTUE9TSVRJT05fUEFTU19BRFZJU09SWRAGEioKJkdVQVJEUkFJTF9ESVNQT1NJVElPTl9DT05USU5VRV9XQVJOSU5HEAcqkAEKFUd1YXJkcmFpbEFwcHJvdmFsS2luZBInCiNHVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9VTlNQRUNJRklFRBAAEiIKHkdVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX0FDVElPThABEioKJkdVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX1JFU1VMVF9SRUxFQVNFEAIqmAEKDEhvb2tEZWNpc2lvbhIdChlIT09LX0RFQ0lTSU9OX1VOU1BFQ0lGSUVEEAASFgoSSE9PS19ERUNJU0lPTl9JTkZPEAESGQoVSE9PS19ERUNJU0lPTl9CTE9DS0VEEAISGgoWSE9PS19ERUNJU0lPTl9NT0RJRklFRBADEhoKFkhPT0tfREVDSVNJT05fQURWSVNPUlkQBCqWAQoQUmV0cnlEaXNwb3NpdGlvbhIhCh1SRVRSWV9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEh0KGVJFVFJZX0RJU1BPU0lUSU9OX1VOS05PV04QARIfChtSRVRSWV9ESVNQT1NJVElPTl9SRVRSWUFCTEUQAhIfChtSRVRSWV9ESVNQT1NJVElPTl9QRVJNQU5FTlQQAyqoAQoOU3RyZWFtUHJvZ3Jlc3MSHwobU1RSRUFNX1BST0dSRVNTX1VOU1BFQ0lGSUVEEAASGwoXU1RSRUFNX1BST0dSRVNTX1VOS05PV04QARIdChlTVFJFQU1fUFJPR1JFU1NfUFJFQ09NTUlUEAISGwoXU1RSRUFNX1BST0dSRVNTX1ZJU0lCTEUQAxIcChhTVFJFQU1fUFJPR1JFU1NfQ09NUExFVEUQBCqEAQoOU291bFByb3ZlbmFuY2USHwobU09VTF9QUk9WRU5BTkNFX1VOU1BFQ0lGSUVEEAASGAoUU09VTF9QUk9WRU5BTkNFX1VTRVIQARIbChdTT1VMX1BST1ZFTkFOQ0VfUFJPSkVDVBACEhoKFlNPVUxfUFJPVkVOQU5DRV9EUklWRVIQAyqtAQoUVGVhbU1lbWJlclN0b3BSZWFzb24SJwojVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fVU5TUEVDSUZJRUQQABIhCh1URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9FUlJPUhABEiUKIVRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0NBTkNFTExFRBACEiIKHlRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0JVREdFVBADMpw5Cg5IYXJuZXNzU2VydmljZRJnChRHZXRDb21wYXRpYmlsaXR5SW5mbxImLm1lY2F0bC52MS5HZXRDb21wYXRpYmlsaXR5SW5mb1JlcXVlc3QaJy5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXNwb25zZRJtChZMaXN0RXhlY3V0aW9uVGVtcGxhdGVzEigubWVjYXRsLnYxLkxpc3RFeGVjdXRpb25UZW1wbGF0ZXNSZXF1ZXN0GikubWVjYXRsLnYxLkxpc3RFeGVjdXRpb25UZW1wbGF0ZXNSZXNwb25zZRJSCg1DcmVhdGVTZXNzaW9uEh8ubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXNwb25zZRJSCg1HZXRTZXJ2ZXJJbmZvEh8ubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXF1ZXN0GiAubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXNwb25zZRJJCgpHZXRTZXNzaW9uEhwubWVjYXRsLnYxLkdldFNlc3Npb25SZXF1ZXN0Gh0ubWVjYXRsLnYxLkdldFNlc3Npb25SZXNwb25zZRJqChVMaXN0R3VhcmRyYWlsQ292ZXJhZ2USJy5tZWNhdGwudjEuTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVxdWVzdBooLm1lY2F0bC52MS5MaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXNwb25zZRJzChhHZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWwSKi5tZWNhdGwudjEuR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVxdWVzdBorLm1lY2F0bC52MS5HZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXNwb25zZRJnChRHZXRTZXNzaW9uVHJhbnNjcmlwdBImLm1lY2F0bC52MS5HZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QaJy5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRJACgdTZXRNb2RlEhkubWVjYXRsLnYxLlNldE1vZGVSZXF1ZXN0GhoubWVjYXRsLnYxLlNldE1vZGVSZXNwb25zZRJPCgxDbG9zZVNlc3Npb24SHi5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbG9zZVNlc3Npb25SZXNwb25zZRJSCg1SZW5hbWVTZXNzaW9uEh8ubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXNwb25zZRJSCg1EZWxldGVTZXNzaW9uEh8ubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXNwb25zZRJVCg5Db21wYWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5Db21wYWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXNwb25zZRJPCgxDbGVhclNlc3Npb24SHi5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbGVhclNlc3Npb25SZXNwb25zZRJMCgtGb3JrU2Vzc2lvbhIdLm1lY2F0bC52MS5Gb3JrU2Vzc2lvblJlcXVlc3QaHi5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXNwb25zZRJHCghDb252ZXJzZRIaLm1lY2F0bC52MS5Db252ZXJzZVJlcXVlc3QaGy5tZWNhdGwudjEuQ29udmVyc2VSZXNwb25zZSgBMAESUgoNUmVzb2x2ZVJ1bkFzaxIfLm1lY2F0bC52MS5SZXNvbHZlUnVuQXNrUmVxdWVzdBogLm1lY2F0bC52MS5SZXNvbHZlUnVuQXNrUmVzcG9uc2USVQoOUmVzb2x2ZVBsYW5Bc2sSIC5tZWNhdGwudjEuUmVzb2x2ZVBsYW5Bc2tSZXF1ZXN0GiEubWVjYXRsLnYxLlJlc29sdmVQbGFuQXNrUmVzcG9uc2USRgoJQ2FuY2VsUnVuEhsubWVjYXRsLnYxLkNhbmNlbFJ1blJlcXVlc3QaHC5tZWNhdGwudjEuQ2FuY2VsUnVuUmVzcG9uc2USQwoIU3RlZXJSdW4SGi5tZWNhdGwudjEuU3RlZXJSdW5SZXF1ZXN0GhsubWVjYXRsLnYxLlN0ZWVyUnVuUmVzcG9uc2USVQoOQ2FuY2VsUnVuU3RlZXISIC5tZWNhdGwudjEuQ2FuY2VsUnVuU3RlZXJSZXF1ZXN0GiEubWVjYXRsLnYxLkNhbmNlbFJ1blN0ZWVyUmVzcG9uc2USWwoQTGlzdE1jcFJlc291cmNlcxIiLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVzcG9uc2USWAoPUmVhZE1jcFJlc291cmNlEiEubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QaIi5tZWNhdGwudjEuUmVhZE1jcFJlc291cmNlUmVzcG9uc2USVQoOTGlzdE1jcFByb21wdHMSIC5tZWNhdGwudjEuTGlzdE1jcFByb21wdHNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USTwoMR2V0TWNwUHJvbXB0Eh4ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QaHy5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVzcG9uc2USVQoOTGlzdE1jcFNvdXJjZXMSIC5tZWNhdGwudjEuTGlzdE1jcFNvdXJjZXNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVzcG9uc2USXgoRUmVmcmVzaE1jcFNvdXJjZXMSIy5tZWNhdGwudjEuUmVmcmVzaE1jcFNvdXJjZXNSZXF1ZXN0GiQubWVjYXRsLnYxLlJlZnJlc2hNY3BTb3VyY2VzUmVzcG9uc2UScwoYTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzEioubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1JlcXVlc3QaKy5tZWNhdGwudjEuTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVzcG9uc2USYQoSTGlzdFRvb2xIaXZlR3JvdXBzEiQubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1JlcXVlc3QaJS5tZWNhdGwudjEuTGlzdFRvb2xIaXZlR3JvdXBzUmVzcG9uc2USSQoKTGlzdEFnZW50cxIcLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVzcG9uc2USTwoMTGlzdENvbW1hbmRzEh4ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdENvbW1hbmRzUmVzcG9uc2USUgoNTGlzdFdvcmt0cmVlcxIfLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVxdWVzdBogLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVzcG9uc2USUAoTU3RyZWFtU2Vzc2lvbkV2ZW50cxIlLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEkwKEVN0cmVhbVNlc3Npb25MaXZlEiMubWVjYXRsLnYxLlN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmMKEldhdGNoU2Vzc2lvbkV2ZW50cxIkLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0GiUubWVjYXRsLnYxLldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlMAESiAEKH0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb24SMS5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QaMi5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlc3BvbnNlEnQKF1JlY2hlY2tNY3BBdXRob3JpemF0aW9uEikubWVjYXRsLnYxLlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBoqLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlKAEwARJxChZDYW5jZWxNY3BBdXRob3JpemF0aW9uEigubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0GikubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAESTwoMTGlzdFNlc3Npb25zEh4ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdFNlc3Npb25zUmVzcG9uc2USWwoQR2V0U3RvcmFnZUhlYWx0aBIiLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVxdWVzdBojLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVzcG9uc2USYQoSUGxhblNlc3Npb25DbGVhbnVwEiQubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlcXVlc3QaJS5tZWNhdGwudjEuUGxhblNlc3Npb25DbGVhbnVwUmVzcG9uc2USUwoTQXBwbHlTZXNzaW9uQ2xlYW51cBIlLm1lY2F0bC52MS5BcHBseVNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFENhbmNlbFNlc3Npb25DbGVhbnVwEiYubWVjYXRsLnYxLkNhbmNlbFNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFEdldFNlc3Npb25DbGVhbnVwSm9iEiYubWVjYXRsLnYxLkdldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iEkkKCkxpc3RTa2lsbHMSHC5tZWNhdGwudjEuTGlzdFNraWxsc1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdFNraWxsc1Jlc3BvbnNlElUKDkxpc3RTa2lsbEZpbGVzEiAubWVjYXRsLnYxLkxpc3RTa2lsbEZpbGVzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0U2tpbGxGaWxlc1Jlc3BvbnNlElIKDVJlYWRTa2lsbEZpbGUSHy5tZWNhdGwudjEuUmVhZFNraWxsRmlsZVJlcXVlc3QaIC5tZWNhdGwudjEuUmVhZFNraWxsRmlsZVJlc3BvbnNlEkAKB0dldFNvdWwSGS5tZWNhdGwudjEuR2V0U291bFJlcXVlc3QaGi5tZWNhdGwudjEuR2V0U291bFJlc3BvbnNlEk8KDEdldFVzZXJNb2RlbBIeLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldFVzZXJNb2RlbFJlc3BvbnNlElUKDlJlZmxlY3RTZXNzaW9uEiAubWVjYXRsLnYxLlJlZmxlY3RTZXNzaW9uUmVxdWVzdBohLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlc3BvbnNlEmEKEkdldExlYXJuaW5nQXR0ZW1wdBIkLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GiUubWVjYXRsLnYxLkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmcKFExpc3RMZWFybmluZ0F0dGVtcHRzEiYubWVjYXRsLnYxLkxpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBonLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1Jlc3BvbnNlEmkKFFJldHJ5TGVhcm5pbmdBdHRlbXB0EicubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QaKC5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USawoWQWJhbmRvbkxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEl4KEUdlbmVyYXRlRHJlYW1QbGFuEiMubWVjYXRsLnYxLkdlbmVyYXRlRHJlYW1QbGFuUmVxdWVzdBokLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlElgKD0RlY2lkZURyZWFtUGxhbhIhLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXF1ZXN0GiIubWVjYXRsLnYxLkRlY2lkZURyZWFtUGxhblJlc3BvbnNlEmoKFUxpc3RMZWFybmluZ1Byb3Bvc2FscxInLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXF1ZXN0GigubWVjYXRsLnYxLkxpc3RMZWFybmluZ1Byb3Bvc2Fsc1Jlc3BvbnNlEmQKE0dldExlYXJuaW5nUHJvcG9zYWwSJS5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaJi5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEm0KFkRlY2lkZUxlYXJuaW5nUHJvcG9zYWwSKC5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaKS5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEmoKFVVuZG9MZWFybmluZ1Byb21vdGlvbhInLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXF1ZXN0GigubWVjYXRsLnYxLlVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEl4KEUxpc3RMZWFybmVkU2tpbGxzEiMubWVjYXRsLnYxLkxpc3RMZWFybmVkU2tpbGxzUmVxdWVzdBokLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlElgKD0dldExlYXJuZWRTa2lsbBIhLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXF1ZXN0GiIubWVjYXRsLnYxLkdldExlYXJuZWRTa2lsbFJlc3BvbnNlEnMKGERpZmZMZWFybmVkU2tpbGxWZXJzaW9ucxIqLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXF1ZXN0GisubWVjYXRsLnYxLkRpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1Jlc3BvbnNlEmMKFEFjdGl2YXRlTGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYQoSUmVqZWN0TGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYgoTQXJjaGl2ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmUKFFJvbGxiYWNrTGVhcm5lZFNraWxsEiYubWVjYXRsLnYxLlJvbGxiYWNrTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJbChBMaXN0U2tpbGxDaGFuZ2VzEiIubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXF1ZXN0GiMubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXNwb25zZRJJCgpMaXN0TW9kZWxzEhwubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXNwb25zZRJJCgpDcmVhdGVUZWFtEhwubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXF1ZXN0Gh0ubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXNwb25zZRJSCg1TcGF3blRlYW1tYXRlEh8ubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXF1ZXN0GiAubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXNwb25zZRJkChNTZW5kVGVhbW1hdGVNZXNzYWdlEiUubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXF1ZXN0GiYubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXNwb25zZRJVCg5DYW5jZWxUZWFtbWF0ZRIgLm1lY2F0bC52MS5DYW5jZWxUZWFtbWF0ZVJlcXVlc3QaIS5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXNwb25zZRI8CgdSdW5UZWFtEhkubWVjYXRsLnYxLlJ1blRlYW1SZXF1ZXN0GhQubWVjYXRsLnYxLlRlYW1FdmVudDABEkMKCExpc3RUZWFtEhoubWVjYXRsLnYxLkxpc3RUZWFtUmVxdWVzdBobLm1lY2F0bC52MS5MaXN0VGVhbVJlc3BvbnNlEkwKC0NsZWFudXBUZWFtEh0ubWVjYXRsLnYxLkNsZWFudXBUZWFtUmVxdWVzdBoeLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlc3BvbnNlEkAKC0FwcHJvdmVQbGFuEh0ubWVjYXRsLnYxLkFwcHJvdmVQbGFuUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmgKGENvbm5lY3RXb3Jrc3BhY2VTZXJ2aWNlcxIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29ubmVjdFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudBJoChhSZXRyeVdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaQoZQ2FuY2VsV29ya3NwYWNlRW5yb2xsbWVudBIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudEKiAQoNY29tLm1lY2F0bC52MUIMSGFybmVzc1Byb3RvUAFaPmdpdGh1Yi5jb20vc3RhY2tsb2svbWVjYXRsL2NvbnRyYWN0cy9nZW4vZ28vbWVjYXRsL3YxO21lY2F0bHYxogIDTVhYqgIJTWVjYXRsLlYxygIJTWVjYXRsXFYx4gIVTWVjYXRsXFYxXEdQQk1ldGFkYXRh6gIKTWVjYXRsOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_google_protobuf_timestamp]); + fileDesc("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIpgDChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSMAoJZXhlY3V0aW9uGAwgASgLMh0ubWVjYXRsLnYxLkV4ZWN1dGlvblNlbGVjdGlvbhIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMSHQoVYWdlbnRfZGVmaW5pdGlvbl9uYW1lGA0gASgJSgQIARACSgQICBAJSgQIBhAHUgl3b3Jrc3BhY2VSEXNvdXJjZV9zZXNzaW9uX2lkUgdwcm9maWxlImwKEkV4ZWN1dGlvblNlbGVjdGlvbhImCgRub25lGAEgASgLMhgubWVjYXRsLnYxLkV4ZWN1dGlvbk5vbmUSLgoIdGVtcGxhdGUYAiABKAsyHC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGUiDwoNRXhlY3V0aW9uTm9uZSIxChFFeGVjdXRpb25UZW1wbGF0ZRIKCgJpZBgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCSIfCh1MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdCJtCh5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USLwoFaXRlbXMYASADKAsyIC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGVJbmZvEhoKEmludmVudG9yeV9yZXZpc2lvbhgCIAEoCSK9AgoVRXhlY3V0aW9uVGVtcGxhdGVJbmZvEi4KCHRlbXBsYXRlGAEgASgLMhwubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSFQoNZGlzcGxheV90b2tlbhgEIAEoCRJECgpleHRlbnNpb25zGAUgAygLMjAubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlSW5mby5FeHRlbnNpb25zRW50cnkSIAoYZGVjbGFyZWRfZXhlY3V0aW9uX2ZpbGVzGAYgASgIEh8KF2RlY2xhcmVkX2J1aWx0X2luX3NoZWxsGAcgASgIGjEKD0V4dGVuc2lvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIrEBCg1NY3BTZXJ2ZXJTcGVjEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEgwKBHR5cGUYAyABKAkSDwoHY29tbWFuZBgEIAEoCRI2CgdoZWFkZXJzGAUgAygLMiUubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMuSGVhZGVyc0VudHJ5Gi4KDEhlYWRlcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIisKFEdldFNlcnZlckluZm9SZXF1ZXN0EhMKC3Byb3ZpZGVyX2lkGAEgASgJIm8KFUdldFNlcnZlckluZm9SZXNwb25zZRIQCghidWlsZF9pZBgBIAEoCRIdChVzZXJ2ZXJfaW1wbGVtZW50YXRpb24YAiABKAkSJQodbGxtX3Byb3ZpZGVyX2Rpc3BsYXlfZW5kcG9pbnQYAyABKAkiHQobR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0IowBChxHZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEhEKCWFwaV9tYWpvchgBIAEoBRIzCgxjYXBhYmlsaXRpZXMYAiABKAsyHS5tZWNhdGwudjEuU2VydmVyQ2FwYWJpbGl0aWVzEhAKCGZlYXR1cmVzGAMgAygJEhIKCmRlcGxveW1lbnQYBCABKAkivQUKElNlcnZlckNhcGFiaWxpdGllcxILCgNtY3AYASABKAgSFgoOc2xhc2hfY29tbWFuZHMYAiABKAgSDgoGbWVtb3J5GAMgASgIEg4KBnNraWxscxgEIAEoCBINCgV0ZWFtcxgFIAEoCBINCgVzaGVsbBgGIAEoCBINCgVpbWFnZRgHIAEoCBINCgVhdWRpbxgIIAEoCBIOCgZhZ2VudHMYCSABKAgSDAoEc291bBgKIAEoCBISCgp1c2VyX21vZGVsGAsgASgIEhcKD21vZGVsX3NlbGVjdGlvbhgMIAEoCBIPCgdwb3N0dXJlGA0gASgJEhEKCXdvcmt0cmVlcxgOIAEoCBISCgpzY2hlZHVsaW5nGA8gASgIEhIKCnJlZmxlY3Rpb24YECABKAgSGgoSbGVhcm5pbmdfcHJvcG9zYWxzGBEgASgIEhYKDmxlYXJuZWRfc2tpbGxzGBIgASgIEhcKD3N0b3JhZ2VfY2xlYW51cBgWIAEoCBI4CgxtYW51YWxfZHJlYW0YEyABKAsyIi5tZWNhdGwudjEuTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSFgoOc3RvcmFnZV9oZWFsdGgYFyABKAgSDQoFc3RlZXIYGCABKAgSGQoRbWFudWFsX2NvbXBhY3Rpb24YGSABKAgSFQoNc2Vzc2lvbl9kZWJ1ZxgaIAEoCBIRCglkZWJ1Z19tY3AYGyABKAgSHAoUd29ya3NwYWNlX2Vucm9sbG1lbnQYHCABKAgSHAoUbWNwX2Nvbm5lY3Rvcl9zdGF0dXMYHSABKAgSEwoLbWNwX3JlZnJlc2gYHiABKAgSGwoTZXhlY3V0aW9uX3RlbXBsYXRlcxgfIAEoCEoECBQQFUoECBUQFlIPbGVnYWN5X2Fkb3B0aW9uUhFzdG9yYWdlX21pZ3JhdGlvbiI1Ch9MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkisgEKIExpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1Jlc3BvbnNlEhQKDGF2YWlsYWJpbGl0eRgBIAEoCRIYChBlbnJvbGxtZW50X3N0YXRlGAIgASgJEjEKCmNvbm5lY3RvcnMYAyADKAsyHS5tZWNhdGwudjEuTWNwQ29ubmVjdG9yU3RhdHVzEhgKEHRvdGFsX2Nvbm5lY3RvcnMYBCABKA0SEQoJdHJ1bmNhdGVkGAUgASgIIk8KEk1jcENvbm5lY3RvclN0YXR1cxIMCgRuYW1lGAEgASgJEhcKD2NhdGFsb2d1ZV9zdGF0ZRgCIAEoCRISCgp0b29sX2NvdW50GAMgASgNIogCChVDcmVhdGVTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgDIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEjAKDnJlc29sdmVkX21vZGVsGAQgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSLwoJcGxhY2VtZW50GAUgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEiYKHnJlc29sdmVkX2FnZW50X2RlZmluaXRpb25fbmFtZRgGIAEoCUoECAIQA1IMY2FwYWJpbGl0aWVzIlIKEVBsYWNlbWVudE1ldGFkYXRhEgwKBGtpbmQYASABKAkSDQoFbGFiZWwYAiABKAkSDgoGYnJhbmNoGAMgASgJEhAKCHJldmlzaW9uGAQgASgJImgKDVJlc29sdmVkTW9kZWwSEwoLcHJvdmlkZXJfaWQYASABKAkSEAoIbW9kZWxfaWQYAiABKAkSFgoOY29udGV4dF93aW5kb3cYAyABKAMSGAoQcmVhc29uaW5nX2VmZm9ydBgEIAEoCSJkChNTZXNzaW9uQ2FwYWJpbGl0aWVzEg0KBWltYWdlGAEgASgIEg0KBWF1ZGlvGAIgASgIEhcKD2V4ZWN1dGlvbl9maWxlcxgDIAEoCBIWCg5idWlsdF9pbl9zaGVsbBgEIAEoCCIwChFHZXRTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjkKEkdldFNlc3Npb25SZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iOgobR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiUgoUQWN0aXZpdHlSZXBsYXlTdGF0dXMSEQoJYXZhaWxhYmxlGAEgASgIEhAKCGNvbXBsZXRlGAIgASgIEhUKDWF1dGhvcml0YXRpdmUYAyABKAgi7QEKHEdldFNlc3Npb25UcmFuc2NyaXB0UmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIwCghtZXNzYWdlcxgCIAMoCzIeLm1lY2F0bC52MS5Db252ZXJzYXRpb25NZXNzYWdlEhAKCGNvbXBsZXRlGAMgASgIEjEKCGFjdGl2aXR5GAQgASgLMh8ubWVjYXRsLnYxLkFjdGl2aXR5UmVwbGF5U3RhdHVzEgwKBGtpbmQYBSABKAkSNAoMcmVsYXRpb25zaGlwGAYgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXAiOQoaU3RyZWFtU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI3ChhTdHJlYW1TZXNzaW9uTGl2ZVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJYChlXYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDgoGY3Vyc29yGAIgASgJEg4KBnJ1bl9pZBgDIAEoCSJcChpXYXRjaFNlc3Npb25FdmVudHNSZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudBIOCgZjdXJzb3IYAiABKAkSDQoFcGhhc2UYAyABKAkiOAoTTGlzdFNlc3Npb25zUmVxdWVzdBIRCglwYWdlX3NpemUYASABKAUSDgoGY3Vyc29yGAIgASgJIk4KCVByaW5jaXBhbBIOCgZpc3N1ZXIYASABKAkSDwoHc3ViamVjdBgCIAEoCRISCgpncmFudF90eXBlGAMgASgJEgwKBG5hbWUYBCABKAki/gQKDlNlc3Npb25TdW1tYXJ5EhIKCnNlc3Npb25faWQYASABKAkSGAoQbW9kaWZpZWRfYXRfdW5peBgCIAEoAxINCgVzdGF0ZRgDIAEoCRINCgV0dXJucxgEIAEoBRIQCghtb2RlbF9pZBgFIAEoCRIXCg9jcmVhdGVkX2F0X3VuaXgYBiABKAMSIwoFb3duZXIYCCABKAsyFC5tZWNhdGwudjEuUHJpbmNpcGFsEgwKBGtpbmQYCSABKAkSNAoMcmVsYXRpb25zaGlwGAogASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXASPQoMY2FwYWJpbGl0aWVzGAsgASgLMicubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcmVhc29uX2NvZGUYDCABKAkSLwoJcGxhY2VtZW50GA8gASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBAgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI+Cgt0b2tlbl91c2FnZRgRIAMoCzIpLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeS5Ub2tlblVzYWdlRW50cnkSFgoOYWN0aXZpdHlfc3RhdGUYEiABKAkaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECAcQCEoECA0QDkoECA4QD1IFdGl0bGVSCXdvcmtzcGFjZVIQdGl0bGVfcHJvdmVuYW5jZSLmAQoTU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFwYXJlbnRfc2Vzc2lvbl9pZBgBIAEoCRIPCgdjYWxsX2lkGAIgASgJEhkKDGJyYW5jaF9pbmRleBgDIAEoBUgAiAEBEhUKDXNjaGVkdWxlX25hbWUYBCABKAkSGQoRb3JpZ2luX3Nlc3Npb25faWQYBSABKAkSDwoHdGVhbV9pZBgGIAEoCRITCgttZW1iZXJfbmFtZRgHIAEoCRIfChdkZWJ1Z190YXJnZXRfc2Vzc2lvbl9pZBgIIAEoCUIPCg1fYnJhbmNoX2luZGV4IpICChxTZXNzaW9uSW52ZW50b3J5Q2FwYWJpbGl0aWVzEhMKC3B1YmxpY19jaGF0GAEgASgIEg8KB2luc3BlY3QYAiABKAgSIAoYYXV0aG9yaXRhdGl2ZV90cmFuc2NyaXB0GAMgASgIEhcKD2FjdGl2aXR5X3JlcGxheRgEIAEoCBIPCgdjb3B5X2lkGAUgASgIEhcKD3ZpZXdfdHJhbnNjcmlwdBgGIAEoCBIMCgRmb3JrGAcgASgIEg4KBnJlbmFtZRgIIAEoCBIOCgZkZWxldGUYCSABKAgSOQoHcmVhc29ucxgKIAEoCzIoLm1lY2F0bC52MS5TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucyKdAQodU2Vzc2lvbkludmVudG9yeUFjdGlvblJlYXNvbnMSEwoLcHVibGljX2NoYXQYASABKAkSDwoHaW5zcGVjdBgCIAEoCRIPCgdjb3B5X2lkGAMgASgJEhcKD3ZpZXdfdHJhbnNjcmlwdBgEIAEoCRIMCgRmb3JrGAUgASgJEg4KBnJlbmFtZRgGIAEoCRIOCgZkZWxldGUYByABKAkibQoUTGlzdFNlc3Npb25zUmVzcG9uc2USKwoIc2Vzc2lvbnMYASADKAsyGS5tZWNhdGwudjEuU2Vzc2lvblN1bW1hcnkSEwoLbmV4dF9jdXJzb3IYAiABKAkSEwoLdG90YWxfY291bnQYAyABKAUiGQoXR2V0U3RvcmFnZUhlYWx0aFJlcXVlc3Qi3gEKD1JldGVudGlvblBvbGljeRIcChRtYWluX21heF9hZ2Vfc2Vjb25kcxgBIAEoAxIWCg5tYWluX21heF9jb3VudBgCIAEoBRIdChVjaGlsZF9tYXhfYWdlX3NlY29uZHMYAyABKAMSFwoPY2hpbGRfbWF4X2NvdW50GAQgASgFEiEKGXNjaGVkdWxlZF9tYXhfYWdlX3NlY29uZHMYBSABKAMSGwoTc2NoZWR1bGVkX21heF9jb3VudBgGIAEoBRIdChVzd2VlcF9jYWRlbmNlX3NlY29uZHMYByABKAMiyQcKGEdldFN0b3JhZ2VIZWFsdGhSZXNwb25zZRIRCglhdmFpbGFibGUYASABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAIgASgJEhUKDWN1cnJlbnRfYnl0ZXMYAyABKAMSHwoXY3VycmVudF9ieXRlc19hdmFpbGFibGUYBCABKAgSGQoRcmVjbGFpbWFibGVfYnl0ZXMYBSABKAMSIwobcmVjbGFpbWFibGVfYnl0ZXNfYXZhaWxhYmxlGAYgASgIEhUKDXNlc3Npb25fY291bnQYByABKAMSEgoKZmlsZV9jb3VudBgIIAEoAxIQCgh2MV9jb3VudBgJIAEoAxIQCgh2Ml9jb3VudBgKIAEoAxISCgptYWluX2NvdW50GAsgASgDEhMKC2NoaWxkX2NvdW50GAwgASgDEhcKD3NjaGVkdWxlZF9jb3VudBgNIAEoAxIVCg11bmtub3duX2NvdW50GA4gASgDEhUKDWNvcnJ1cHRfY291bnQYDyABKAMSKgoGcG9saWN5GBAgASgLMhoubWVjYXRsLnYxLlJldGVudGlvblBvbGljeRIXCg9sYXN0X3N3ZWVwX3VuaXgYESABKAMSHAoUbGFzdF9zd2VlcF9hdmFpbGFibGUYEiABKAgSFwoPbmV4dF9zd2VlcF91bml4GBMgASgDEhwKFG5leHRfc3dlZXBfYXZhaWxhYmxlGBQgASgIEhIKCmFjdGl2ZV9qb2IYFSABKAkSFAoMbGFzdF9mYWlsdXJlGBYgASgJEiQKHG93bmVybGVzc19zZXNzaW9uc19hdmFpbGFibGUYFyABKAgSLQolb3duZXJsZXNzX3Nlc3Npb25zX3VuYXZhaWxhYmxlX3JlYXNvbhgYIAEoCRIfChdvd25lcmxlc3Nfc2Vzc2lvbl9jb3VudBgZIAEoAxIdChVvd25lcmxlc3Nfc2Vzc2lvbl9pZHMYGiADKAkSJwofb3duZXJsZXNzX3Nlc3Npb25faWRzX3RydW5jYXRlZBgbIAEoCBIlCh1vd25lcmxlc3Nfc2NoZWR1bGVzX2F2YWlsYWJsZRgcIAEoCBIuCiZvd25lcmxlc3Nfc2NoZWR1bGVzX3VuYXZhaWxhYmxlX3JlYXNvbhgdIAEoCRIgChhvd25lcmxlc3Nfc2NoZWR1bGVfY291bnQYHiABKAMSIAoYb3duZXJsZXNzX3NjaGVkdWxlX25hbWVzGB8gAygJEioKIm93bmVybGVzc19zY2hlZHVsZV9uYW1lc190cnVuY2F0ZWQYICABKAgi2QIKDUNsZWFudXBDb3VudHMSDQoFdG90YWwYASABKAUSNQoHYnlfa2luZBgCIAMoCzIkLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5S2luZEVudHJ5EjcKCGJ5X3N0YXRlGAMgAygLMiUubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlTdGF0ZUVudHJ5EjkKCWJ5X3JlYXNvbhgEIAMoCzImLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5UmVhc29uRW50cnkaLQoLQnlLaW5kRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARouCgxCeVN0YXRlRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARovCg1CeVJlYXNvbkVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEihgEKEENsZWFudXBDYW5kaWRhdGUSEgoKc2Vzc2lvbl9pZBgBIAEoCRIMCgRraW5kGAIgASgJEg0KBXN0YXRlGAMgASgJEg4KBnJlYXNvbhgEIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAUgASgDEhcKD2VzdGltYXRlZF9ieXRlcxgGIAEoAyIqChlQbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0Eg0KBWtpbmRzGAEgAygJItMCChpQbGFuU2Vzc2lvbkNsZWFudXBSZXNwb25zZRIaChJjb25maXJtYXRpb25fdG9rZW4YASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRISCgpnZW5lcmF0aW9uGAQgASgJEhYKDnBvbGljeV92ZXJzaW9uGAUgASgJEi0KCGVsaWdpYmxlGAYgAygLMhsubWVjYXRsLnYxLkNsZWFudXBDYW5kaWRhdGUSKwoJcHJvdGVjdGVkGAcgASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMSFwoPZXN0aW1hdGVkX2J5dGVzGAggASgDEhYKDnBsYW5uZWRfam9iX2lkGAkgASgJEjEKD2VsaWdpYmxlX2NvdW50cxgKIAEoCzIYLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzIkEKGkFwcGx5U2Vzc2lvbkNsZWFudXBSZXF1ZXN0EiMKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCUIHukgEcgIQASI2ChtDYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjYKG0dldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiTQoQQ2xlYW51cEl0ZW1FcnJvchITCgtpdGVtX2hhbmRsZRgBIAEoCRITCgtyZWFzb25fY29kZRgCIAEoCRIPCgdtZXNzYWdlGAMgASgJIqwBCgpDbGVhbnVwSm9iEg4KBmpvYl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIRCglwcm9jZXNzZWQYAyABKAUSDwoHZGVsZXRlZBgEIAEoBRIPCgdza2lwcGVkGAUgASgFEg0KBXN0YWxlGAYgASgFEg4KBmZhaWxlZBgHIAEoBRIrCgZlcnJvcnMYCCADKAsyGy5tZWNhdGwudjEuQ2xlYW51cEl0ZW1FcnJvciJWCg5TZXRNb2RlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEicKBG1vZGUYAiABKA4yGS5tZWNhdGwudjEuUGVybWlzc2lvbk1vZGUiNgoPU2V0TW9kZVJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiIyChNDbG9zZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiFgoUQ2xvc2VTZXNzaW9uUmVzcG9uc2UiSwoUUmVuYW1lU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIWCgV0aXRsZRgCIAEoCUIHukgEcgIQASI8ChVSZW5hbWVTZXNzaW9uUmVzcG9uc2USIwoHc2Vzc2lvbhgBIAEoCzISLm1lY2F0bC52MS5TZXNzaW9uIjMKFERlbGV0ZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiFwoVRGVsZXRlU2Vzc2lvblJlc3BvbnNlIm8KE0NsZWFyU2Vzc2lvblJlcXVlc3QSIgoRc291cmNlX3Nlc3Npb25faWQYASABKAlCB7pIBHICEAESHgoRd29ya3RyZWVfc2VsZWN0b3IYAiABKAlIAIgBAUIUChJfd29ya3RyZWVfc2VsZWN0b3IiWwoUQ2xlYXJTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIvCglwbGFjZW1lbnQYAiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGEivgEKEkZvcmtTZXNzaW9uUmVxdWVzdBIiChFzb3VyY2Vfc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARINCgV0aXRsZRgCIAEoCRIYChByZWFzb25pbmdfZWZmb3J0GAMgASgJEh4KEXdvcmt0cmVlX3NlbGVjdG9yGAQgASgJSACIAQESEwoLcHJvdmlkZXJfaWQYBSABKAkSEAoIbW9kZWxfaWQYBiABKAlCFAoSX3dvcmt0cmVlX3NlbGVjdG9yIloKE0ZvcmtTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIvCglwbGFjZW1lbnQYAiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGEiOwoQQ29udGV4dE9jY3VwYW5jeRIUCgxpbnB1dF90b2tlbnMYASABKAMSEQoJZXN0aW1hdGVkGAIgASgIIqwGCgdTZXNzaW9uEhIKCnNlc3Npb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkSJwoEbW9kZRgDIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIhCgZsaW1pdHMYBSABKAsyES5tZWNhdGwudjEuTGltaXRzEg0KBXR1cm5zGAYgASgFEhIKCnRvb2xfY2FsbHMYByABKAUSFwoPY3JlYXRlZF9hdF91bml4GAggASgDEjAKDnJlc29sdmVkX21vZGVsGAkgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSDAoEa2luZBgOIAEoCRI0CgxyZWxhdGlvbnNoaXAYDyABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFkZWJ1Z19tY3Bfc2VydmVycxgQIAMoCRIXCg9kZWJ1Z19tY3BfdG9vbHMYESADKAkSLwoJcGxhY2VtZW50GBIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBMgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI3Cgt0b2tlbl91c2FnZRgUIAMoCzIiLm1lY2F0bC52MS5TZXNzaW9uLlRva2VuVXNhZ2VFbnRyeRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgVIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEj0KGGxhdGVzdF9jb250ZXh0X29jY3VwYW5jeRgWIAEoCzIbLm1lY2F0bC52MS5Db250ZXh0T2NjdXBhbmN5GkgKD1Rva2VuVXNhZ2VFbnRyeRILCgNrZXkYASABKAkSJAoFdmFsdWUYAiABKAsyFS5tZWNhdGwudjEuVG9rZW5Vc2FnZToCOAFKBAgEEAVKBAgKEAtKBAgLEAxKBAgMEA1KBAgNEA5SCXdvcmtzcGFjZVIFdGl0bGVSDGNhcGFiaWxpdGllc1IQdGl0bGVfcHJvdmVuYW5jZVIaYWRvcHRpb25fc291cmNlX3Nlc3Npb25faWQilQEKDFNlc3Npb25UaXRsZRINCgV0aXRsZRgBIAEoCRISCgpwcm92ZW5hbmNlGAIgASgJEhgKEGdlbmVyYXRpb25fc3RhdGUYAyABKAkSNgoObGF0ZXN0X2F0dGVtcHQYBCABKAsyHi5tZWNhdGwudjEuVGl0bGVBdHRlbXB0U3VtbWFyeRIQCghyZXZpc2lvbhgFIAEoBCI4ChNUaXRsZUF0dGVtcHRTdW1tYXJ5EgoKAmlkGAEgASgJEg8KB291dGNvbWUYAiABKAlKBAgDEAQioQEKClRva2VuVXNhZ2USHwoFdG90YWwYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USMQoGbW9kZWxzGAIgAygLMiEubWVjYXRsLnYxLlRva2VuVXNhZ2UuTW9kZWxzRW50cnkaPwoLTW9kZWxzRW50cnkSCwoDa2V5GAEgASgJEh8KBXZhbHVlGAIgASgLMhAubWVjYXRsLnYxLlVzYWdlOgI4ASLEAgoPQ29udmVyc2VSZXF1ZXN0EiMKBnByb21wdBgBIAEoCzIRLm1lY2F0bC52MS5Qcm9tcHRIABImCgVyZXRyeRgCIAEoCzIVLm1lY2F0bC52MS5SZXRyeVN0YXJ0SAASNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAEi4KDGNhbmNlbF9jaGlsZBgMIAEoCzIWLm1lY2F0bC52MS5DYW5jZWxDaGlsZEgAEiEKBXN0ZWVyGA0gASgLMhAubWVjYXRsLnYxLlN0ZWVySAASLgoMc3RlZXJfY2FuY2VsGA4gASgLMhYubWVjYXRsLnYxLlN0ZWVyQ2FuY2VsSABCBgoEa2luZCIzChBDb252ZXJzZVJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IpwBCgdDb250ZW50EiUKBGtpbmQYASABKA4yFy5tZWNhdGwudjEuQ29udGVudC5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCSI8CgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABIOCgpLSU5EX0lNQUdFEAESDgoKS0lORF9BVURJTxACIpADCgxDb250ZW50QmxvY2sSKgoEa2luZBgBIAEoDjIcLm1lY2F0bC52MS5Db250ZW50QmxvY2suS2luZBIRCgltaW1lX3R5cGUYAiABKAkSDAoEZGF0YRgDIAEoDBILCgN1cmwYBCABKAkSDAoEdGV4dBgFIAEoCRIMCgRuYW1lGAYgASgJEg0KBXRpdGxlGAcgASgJEhMKC2Rlc2NyaXB0aW9uGAggASgJEgwKBHNpemUYCSABKAMSEAoIYXVkaWVuY2UYCiADKAkSEAoIcHJpb3JpdHkYCyABKAESFQoNbGFzdF9tb2RpZmllZBgMIAEoCSKcAQoES2luZBIUChBLSU5EX1VOU1BFQ0lGSUVEEAASDQoJS0lORF9URVhUEAESDgoKS0lORF9JTUFHRRACEg4KCktJTkRfQVVESU8QAxIWChJLSU5EX1JFU09VUkNFX0xJTksQBBIaChZLSU5EX0VNQkVEREVEX1JFU09VUkNFEAUSGwoXS0lORF9TVFJVQ1RVUkVEX0NPTlRFTlQQBiIpCgpSZXRyeVN0YXJ0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEifgoGUHJvbXB0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEdGV4dBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50EiYKHnNlcnZlcl9vd25lZF9wbGFuX2NvbnRpbnVhdGlvbhgEIAEoCCLXAQoOUmVzdW1lQXBwcm92YWwSFwoGYXNrX2lkGAEgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYAyABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMSFwoPZXhwZWN0ZWRfcnVuX2lkGAQgASgJEhEKCXJldmlld19pZBgFIAEoCRI4Cg5ndWFyZHJhaWxfa2luZBgGIAEoDjIgLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbEtpbmRKBAgCEANSBWFsbG93IiEKBkNhbmNlbBIXCg9leHBlY3RlZF9ydW5faWQYASABKAkiKAoLQ2FuY2VsQ2hpbGQSGQoIY2hpbGRfaWQYASABKAlCB7pIBHICEAEiZQoFU3RlZXISDAoEdGV4dBgBIAEoCRISCgptZXNzYWdlX2lkGAIgASgJEiEKBXBhcnRzGAMgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSFwoPZXhwZWN0ZWRfcnVuX2lkGAQgASgJIjoKC1N0ZWVyQ2FuY2VsEhIKCm1lc3NhZ2VfaWQYASABKAkSFwoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJIvYBChRSZXNvbHZlUnVuQXNrUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIXCgZhc2tfaWQYAyABKAlCB7pIBHICEAESOQoHdmVyZGljdBgEIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAxIRCglyZXZpZXdfaWQYBSABKAkSOAoOZ3VhcmRyYWlsX2tpbmQYBiABKA4yIC5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxLaW5kIjcKFVJlc29sdmVSdW5Bc2tSZXNwb25zZRIOCgZydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIqoBChVSZXNvbHZlUGxhbkFza1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESFwoGYXNrX2lkGAMgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYBCABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMiOAoWUmVzb2x2ZVBsYW5Bc2tSZXNwb25zZRIOCgZydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIlEKEENhbmNlbFJ1blJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAEiIwoRQ2FuY2VsUnVuUmVzcG9uc2USDgoGcnVuX2lkGAEgASgJIpACCg9TdGVlclJ1blJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESDAoEdGV4dBgDIAEoCRIrCgVwYXJ0cxgEIAMoCzISLm1lY2F0bC52MS5Db250ZW50Qgi6SAWSAQIQEBIbCgptZXNzYWdlX2lkGAUgASgJQge6SARyAhhAOma6SGMaYQoRc3RlZXJfcnVuLmNvbnRlbnQSI3RleHQgYW5kIHBhcnRzIGNhbm5vdCBib3RoIGJlIGVtcHR5Gid0aGlzLnRleHQgIT0gJycgfHwgc2l6ZSh0aGlzLnBhcnRzKSA+IDAiYAoQU3RlZXJSdW5SZXNwb25zZRIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIOCgZydW5faWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCSJzChVDYW5jZWxSdW5TdGVlclJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESGwoKbWVzc2FnZV9pZBgDIAEoCUIHukgEcgIYQCJmChZDYW5jZWxSdW5TdGVlclJlc3BvbnNlEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEg4KBnJ1bl9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJImgKJkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIQoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCUIHukgEcgIQASI2CidHZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uUmVzcG9uc2USCwoDdXJsGAEgASgJIrQBCh5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkIKH1JlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQiswEKHUNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSGAoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCRI0Cg9yZXN1bWVfYXBwcm92YWwYCiABKAsyGS5tZWNhdGwudjEuUmVzdW1lQXBwcm92YWxIABIjCgZjYW5jZWwYCyABKAsyES5tZWNhdGwudjEuQ2FuY2VsSABCCQoHY29udHJvbCJBCh5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQikAEKDUF1dGhvcml6YXRpb24SGAoQYXV0aG9yaXphdGlvbl9pZBgBIAEoCRIPCgdjYWxsX2lkGAIgASgJEi4KCmV4cGlyZXNfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEg4KBnN0YXR1cxgEIAEoCRIUCgxkaXNwbGF5X25hbWUYBSABKAkiPgoXUGxhbkNvbnRpbnVhdGlvbkZhaWx1cmUSEwoLcGxhbl9ydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIrcHCgVFdmVudBIMCgR0eXBlGAEgASgJEgsKA3NlcRgCIAEoAxIMCgR0dXJuGAMgASgFEgwKBHRleHQYBCABKAkSJgoJdG9vbF9jYWxsGAUgASgLMhMubWVjYXRsLnYxLlRvb2xDYWxsEioKC3Rvb2xfcmVzdWx0GAYgASgLMhUubWVjYXRsLnYxLlRvb2xSZXN1bHQSJQoDYXNrGAcgASgLMhgubWVjYXRsLnYxLlBlcm1pc3Npb25Bc2sSIQoGcmVzdWx0GAggASgLMhEubWVjYXRsLnYxLlJlc3VsdBIkCgh0dXJuX2VuZBgKIAEoCzISLm1lY2F0bC52MS5UdXJuRW5kEh0KBGhvb2sYCyABKAsyDy5tZWNhdGwudjEuSG9vaxIlCghzdWJhZ2VudBgMIAEoCzITLm1lY2F0bC52MS5TdWJhZ2VudBIdCgR0ZWFtGA0gASgLMg8ubWVjYXRsLnYxLlRlYW0SJQoIcGFyYWxsZWwYDiABKAsyEy5tZWNhdGwudjEuUGFyYWxsZWwSLAoIc2NoZWR1bGUYDyABKAsyGi5tZWNhdGwudjEuU2NoZWR1bGVQYXlsb2FkEiUKCGFwcHJvdmFsGBAgASgLMhMubWVjYXRsLnYxLkFwcHJvdmFsEioKC3VzZXJfcHJvbXB0GBEgASgLMhUubWVjYXRsLnYxLlVzZXJQcm9tcHQSOAoSY29tcGFjdGlvbl9hcmNoaXZlGBIgASgLMhwubWVjYXRsLnYxLkNvbXBhY3Rpb25BcmNoaXZlEiMKBXN0ZWVyGBMgASgLMhQubWVjYXRsLnYxLlN0ZWVyRWNobxIqCg1zdGVlcl9vdXRjb21lGBQgASgLMhMubWVjYXRsLnYxLlN0ZWVyQWNrEioKC21vZGVsX3JldHJ5GBUgASgLMhUubWVjYXRsLnYxLk1vZGVsUmV0cnkSDgoGcnVuX2lkGBYgASgJEiYKBXRpdGxlGBcgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRIvCg1hdXRob3JpemF0aW9uGBggASgLMhgubWVjYXRsLnYxLkF1dGhvcml6YXRpb24SMgoPY29udHJvbF9yZWZ1c2VkGBkgASgLMhkubWVjYXRsLnYxLkNvbnRyb2xSZWZ1c2VkEkUKGXBsYW5fY29udGludWF0aW9uX2ZhaWx1cmUYGiABKAsyIi5tZWNhdGwudjEuUGxhbkNvbnRpbnVhdGlvbkZhaWx1cmVKBAgJEApSBXVzYWdlIjIKDkNvbnRyb2xSZWZ1c2VkEg4KBmFza19pZBgBIAEoCRIQCghjYXRlZ29yeRgCIAEoCSJ4CgpNb2RlbFJldHJ5EjYKEXJldHJ5X2Rpc3Bvc2l0aW9uGAEgASgOMhsubWVjYXRsLnYxLlJldHJ5RGlzcG9zaXRpb24SMgoPc3RyZWFtX3Byb2dyZXNzGAIgASgOMhkubWVjYXRsLnYxLlN0cmVhbVByb2dyZXNzIlAKCVN0ZWVyRWNobxIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudCJoCghTdGVlckFjaxIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIMCgR0ZXh0GAIgASgJEhAKCHByb21vdGVkGAMgASgIEhIKCm1lc3NhZ2VfaWQYBCABKAkiLQoMR3VhcmRyYWlsUmVmEgsKA3JlZhgBIAEoCRIQCghjYXRlZ29yeRgCIAEoCSKvAwoPR3VhcmRyYWlsUmV2aWV3EhEKCXJldmlld19pZBgBIAEoCRIkCgNqb2IYAiABKA4yFy5tZWNhdGwudjEuR3VhcmRyYWlsSm9iEjIKCmFzc2Vzc21lbnQYAyABKA4yHi5tZWNhdGwudjEuR3VhcmRyYWlsQXNzZXNzbWVudBIyCgppbnNwZWN0aW9uGAQgASgOMh4ubWVjYXRsLnYxLkd1YXJkcmFpbEluc3BlY3Rpb24SNAoLZGlzcG9zaXRpb24YBSABKA4yHy5tZWNhdGwudjEuR3VhcmRyYWlsRGlzcG9zaXRpb24SEwoLcmVhc29uX2NvZGUYBiABKAkSDwoHcnVsZV9pZBgHIAEoCRITCgtydWxlX29yaWdpbhgIIAEoCRIbChNjaGVja2VyX3Byb3ZpZGVyX2lkGAkgASgJEhgKEGNoZWNrZXJfbW9kZWxfaWQYCiABKAkSKQoIY29uY2VybnMYCyADKAsyFy5tZWNhdGwudjEuR3VhcmRyYWlsUmVmEigKB3NvdXJjZXMYDCADKAsyFy5tZWNhdGwudjEuR3VhcmRyYWlsUmVmIqcBChZHdWFyZHJhaWxBcHByb3ZhbFNjb3BlEhEKCXJldmlld19pZBgBIAEoCRIuCgRraW5kGAIgASgOMiAubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsS2luZBIUCgxncmFudF9kaWdlc3QYAyABKAkSFAoMc2Vzc2lvbl9vbmx5GAQgASgIEhgKEHJlcGVhdF9hdmFpbGFibGUYBSABKAhKBAgGEAciMgocTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJItMBChZHdWFyZHJhaWxDb3ZlcmFnZUVudHJ5EgwKBHRvb2wYASABKAkSDQoFcGhhc2UYAiABKAkSJAoDam9iGAMgASgOMhcubWVjYXRsLnYxLkd1YXJkcmFpbEpvYhIMCgRtb2RlGAQgASgJEg8KB3J1bGVfaWQYBSABKAkSEwoLcnVsZV9vcmlnaW4YBiABKAkSMgoKaW5zcGVjdGlvbhgHIAEoDjIeLm1lY2F0bC52MS5HdWFyZHJhaWxJbnNwZWN0aW9uEg4KBnJlYXNvbhgIIAEoCSKbAQodTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVzcG9uc2USDwoHZW5hYmxlZBgBIAEoCBIbChNjaGVja2VyX3Byb3ZpZGVyX2lkGAIgASgJEhgKEGNoZWNrZXJfbW9kZWxfaWQYAyABKAkSMgoHZW50cmllcxgEIAMoCzIhLm1lY2F0bC52MS5HdWFyZHJhaWxDb3ZlcmFnZUVudHJ5IkgKH0dldEd1YXJkcmFpbFJldmlld0RldGFpbFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIRCglyZXZpZXdfaWQYAiABKAkicwogR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVzcG9uc2USEQoJcmV2aWV3X2lkGAEgASgJEg8KB2NvbmNlcm4YAiABKAkSFgoOc291cmNlX2Rpc3BsYXkYAyABKAkSEwoLbmV4dF9hY3Rpb24YBCABKAkikAEKCEFwcHJvdmFsEg4KBmFza19pZBgBIAEoCRIMCgR0b29sGAMgASgJEg8KB2NhbGxfaWQYBCABKAkSKwoHdmVyZGljdBgGIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3QSDgoGb3JpZ2luGAcgASgJSgQIAhADSgQIBRAGUgxhbGxvd19hbHdheXMiUAoKVXNlclByb21wdBIMCgR0ZXh0GAEgASgJEiEKBXBhcnRzGAIgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSEQoJc3ludGhldGljGAMgASgIIkUKEUNvbXBhY3Rpb25BcmNoaXZlEjAKCHJlcGxhY2VkGAEgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2Ui7wEKE0NvbnZlcnNhdGlvbk1lc3NhZ2USDAoEcm9sZRgBIAEoCRIMCgR0ZXh0GAIgASgJEicKCnRvb2xfY2FsbHMYAyADKAsyEy5tZWNhdGwudjEuVG9vbENhbGwSKgoLdG9vbF9yZXN1bHQYBCABKAsyFS5tZWNhdGwudjEuVG9vbFJlc3VsdBIRCglyZWFzb25pbmcYBSABKAkSFgoOcHJvdmlkZXJfcGhhc2UYBiABKAkSIQoFcGFydHMYByADKAsyEi5tZWNhdGwudjEuQ29udGVudBIZChFyZWFzb25pbmdfaXRlbV9pZBgIIAEoCSJ2Cg9TY2hlZHVsZVBheWxvYWQSFQoNc2NoZWR1bGVfbmFtZRgBIAEoCRIPCgdmaXJlX2lkGAIgASgJEhIKCnNlc3Npb25faWQYAyABKAkSDAoEa2luZBgEIAEoCRIMCgRzdG9wGAUgASgJEgsKA2VychgGIAEoCSKOAQoESG9vaxINCgVwaGFzZRgBIAEoCRIMCgR0b29sGAIgASgJEikKCGRlY2lzaW9uGAMgASgOMhcubWVjYXRsLnYxLkhvb2tEZWNpc2lvbhIPCgdjYWxsX2lkGAQgASgJEi0KCWd1YXJkcmFpbBgFIAEoCzIaLm1lY2F0bC52MS5HdWFyZHJhaWxSZXZpZXciqAIKD1JvdXRpbmdEZWNpc2lvbhIPCgdiYWNrZW5kGAEgASgJEhgKEGNsYXNzaWZpZXJfbW9kZWwYAiABKAkSGgoSY2FuZGlkYXRlX2NhdGVnb3J5GAMgASgJEhcKD2NhbmRpZGF0ZV9tb2RlbBgEIAEoCRIXCgpjb25maWRlbmNlGAUgASgBSACIAQESHwoSbWluaW11bV9jb25maWRlbmNlGAYgASgBSAGIAQESDwoHb3V0Y29tZRgHIAEoCRIaChJjb25zZWN1dGl2ZV9taXNzZXMYCCABKAUSEgoKbWlzc19saW1pdBgJIAEoBRIUCgxicmVha2VyX29wZW4YCiABKAhCDQoLX2NvbmZpZGVuY2VCFQoTX21pbmltdW1fY29uZmlkZW5jZSKKBAoIU3ViYWdlbnQSFgoOcGFyZW50X2NhbGxfaWQYASABKAkSEAoIY2hpbGRfaWQYAiABKAkSDAoEZ29hbBgDIAEoCRIRCgl0b29sX25hbWUYBCABKAkSEAoIaXNfZXJyb3IYBSABKAgSEgoKdG9vbF9jb3VudBgGIAEoBRIfCgV1c2FnZRgHIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIMCgRzdG9wGAggASgJEhMKC2R1cmF0aW9uX21zGAkgASgDEhIKCmJhY2tncm91bmQYCiABKAgSFwoPcm91dGVkX2NhdGVnb3J5GAsgASgJEhQKDHJvdXRlZF9tb2RlbBgMIAEoCRINCgVtb2RlbBgNIAEoCRISCgppbm5lcl9raW5kGA4gASgJEgwKBHRleHQYDyABKAkSDgoGZGV0YWlsGBAgASgJEg0KBWNhdXNlGBEgASgJEhYKDnJvdXRpbmdfcmVhc29uGBIgASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YEyABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBQgASgJEhAKCHByb3ZpZGVyGBUgASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgWIAEoCUITChFfcm91dGluZ19kZWNpc2lvbiKmAgoOVGVhbU1lbWJlclNwZWMSDAoEbmFtZRgBIAEoCRIMCgRyb2xlGAIgASgJEhAKCG11dGF0aW5nGAMgASgIEgwKBGxlYWQYBCABKAgSFwoPcm91dGVkX2NhdGVnb3J5GAUgASgJEhQKDHJvdXRlZF9tb2RlbBgGIAEoCRINCgVtb2RlbBgHIAEoCRIWCg5yb3V0aW5nX3JlYXNvbhgIIAEoCRI5ChByb3V0aW5nX2RlY2lzaW9uGAkgASgLMhoubWVjYXRsLnYxLlJvdXRpbmdEZWNpc2lvbkgAiAEBEhAKCHByb3ZpZGVyGAogASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgLIAEoCUITChFfcm91dGluZ19kZWNpc2lvbiL6AwoEVGVhbRIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIPCgd0ZWFtX2lkGAIgASgJEikKBnJvc3RlchgDIAMoCzIZLm1lY2F0bC52MS5UZWFtTWVtYmVyU3BlYxIOCgZtZW1iZXIYBCABKAkSEgoKaW5uZXJfa2luZBgFIAEoCRIMCgR0ZXh0GAYgASgJEhEKCXRvb2xfbmFtZRgHIAEoCRIOCgZkZXRhaWwYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSDgoGcm91bmRzGAogASgFEgwKBHN0b3AYCyABKAkSHwoFdXNhZ2UYDCABKAsyEC5tZWNhdGwudjEuVXNhZ2USFAoMY29udGV4dF91c2VkGA0gASgDEhYKDmNvbnRleHRfd2luZG93GA4gASgDEiIKBXRhc2tzGA8gAygLMhMubWVjYXRsLnYxLlRlYW1UYXNrEigKCGZpbmRpbmdzGBAgAygLMhYubWVjYXRsLnYxLlRlYW1GaW5kaW5nEjYKDGRpc3Bvc2l0aW9ucxgRIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SGQoRbWVtYmVyX3Nlc3Npb25faWQYEiABKAkSDQoFY2F1c2UYEyABKAkSGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBQgASgJIo4FCghQYXJhbGxlbBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIMCgRraW5kGAIgASgJEgwKBGpvaW4YAyABKAkSFAoMYnJhbmNoX2NvdW50GAQgASgFEhQKDGJyYW5jaF9pbmRleBgFIAEoBRIUCgxicmFuY2hfbGFiZWwYBiABKAkSDAoEZ29hbBgHIAEoCRIRCgl0b29sX25hbWUYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSEgoKdG9vbF9jb3VudBgKIAEoBRIOCgZmYWlsZWQYCyABKAgSDAoEc3RvcBgNIAEoCRIfCgV1c2FnZRgOIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgPIAEoAxIOCgZ3aW5uZXIYECABKAUSEAoIY2hpbGRfaWQYEiABKAkSFwoPcm91dGVkX2NhdGVnb3J5GBMgASgJEhQKDHJvdXRlZF9tb2RlbBgUIAEoCRINCgVtb2RlbBgVIAEoCRISCgppbm5lcl9raW5kGBYgASgJEgwKBHRleHQYFyABKAkSDgoGZGV0YWlsGBggASgJEhYKDnJvdXRpbmdfcmVhc29uGBkgASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YGiABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBsgASgJEhAKCHByb3ZpZGVyGBwgASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgdIAEoCUITChFfcm91dGluZ19kZWNpc2lvbkoECAwQDUoECBEQElIJd29ya3NwYWNlUhB3aW5uZXJfd29ya3NwYWNlIjIKCFRvb2xDYWxsEgoKAmlkGAEgASgJEgwKBG5hbWUYAiABKAkSDAoEYXJncxgDIAEoCSKFAQoKVG9vbFJlc3VsdBIPCgdjYWxsX2lkGAEgASgJEg8KB2NvbnRlbnQYAiABKAkSEAoIaXNfZXJyb3IYAyABKAgSJwoGYmxvY2tzGAQgAygLMhcubWVjYXRsLnYxLkNvbnRlbnRCbG9jaxIaChJzdHJ1Y3R1cmVkX2NvbnRlbnQYBSABKAkiowEKDVBlcm1pc3Npb25Bc2sSDgoGYXNrX2lkGAEgASgJEgwKBHRvb2wYAiABKAkSDAoEYXJncxgDIAEoCRIOCgZyZWFzb24YBCABKAkSNAoJZ3VhcmRyYWlsGAUgASgLMiEubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsU2NvcGUSFAoHY2FsbF9pZBgGIAEoCUgAiAEBQgoKCF9jYWxsX2lkIoUCCgZSZXN1bHQSDAoEc3RvcBgBIAEoCRIMCgR0ZXh0GAIgASgJEh8KBXVzYWdlGAMgASgLMhAubWVjYXRsLnYxLlVzYWdlEg0KBWVycm9yGAQgASgJEjsKEXJldHJ5X2Rpc3Bvc2l0aW9uGAYgASgOMhsubWVjYXRsLnYxLlJldHJ5RGlzcG9zaXRpb25IAIgBARI3Cg9zdHJlYW1fcHJvZ3Jlc3MYByABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3NIAYgBAUIUChJfcmV0cnlfZGlzcG9zaXRpb25CEgoQX3N0cmVhbV9wcm9ncmVzc0oECAUQBlIJcGVybWFuZW50IlIKB1R1cm5FbmQSHwoFdXNhZ2UYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USEwoLZHVyYXRpb25fbXMYAiABKAMSEQoJZXN0aW1hdGVkGAMgASgIIoUBCgVVc2FnZRIUCgxpbnB1dF90b2tlbnMYASABKAMSFQoNb3V0cHV0X3Rva2VucxgCIAEoAxIZChFjYWNoZV9yZWFkX3Rva2VucxgDIAEoAxIaChJjYWNoZV93cml0ZV90b2tlbnMYBCABKAMSGAoQcmVhc29uaW5nX3Rva2VucxgFIAEoAyKQAQoLTWNwUmVzb3VyY2USDgoGc2VydmVyGAEgASgJEgsKA3VyaRgCIAEoCRIMCgRuYW1lGAMgASgJEg0KBXRpdGxlGAQgASgJEhMKC2Rlc2NyaXB0aW9uGAUgASgJEhEKCW1pbWVfdHlwZRgGIAEoCRIMCgRzaXplGAcgASgDEhEKCXJlYWRfb25seRgIIAEoCCIpChdMaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBIOCgZzZXJ2ZXIYASABKAkiRQoYTGlzdE1jcFJlc291cmNlc1Jlc3BvbnNlEikKCXJlc291cmNlcxgBIAMoCzIWLm1lY2F0bC52MS5NY3BSZXNvdXJjZSJRChNNY3BSZXNvdXJjZUNvbnRlbnRzEgsKA3VyaRgBIAEoCRIRCgltaW1lX3R5cGUYAiABKAkSDAoEdGV4dBgDIAEoCRIMCgRibG9iGAQgASgMIkcKFlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QSFwoGc2VydmVyGAEgASgJQge6SARyAhABEhQKA3VyaRgCIAEoCUIHukgEcgIQASJLChdSZWFkTWNwUmVzb3VyY2VSZXNwb25zZRIwCghjb250ZW50cxgBIAMoCzIeLm1lY2F0bC52MS5NY3BSZXNvdXJjZUNvbnRlbnRzIlcKEU1jcFByb21wdEFyZ3VtZW50EgwKBG5hbWUYASABKAkSDQoFdGl0bGUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSEAoIcmVxdWlyZWQYBCABKAgifgoJTWNwUHJvbXB0Eg4KBnNlcnZlchgBIAEoCRIMCgRuYW1lGAIgASgJEg0KBXRpdGxlGAMgASgJEhMKC2Rlc2NyaXB0aW9uGAQgASgJEi8KCWFyZ3VtZW50cxgFIAMoCzIcLm1lY2F0bC52MS5NY3BQcm9tcHRBcmd1bWVudCInChVMaXN0TWNwUHJvbXB0c1JlcXVlc3QSDgoGc2VydmVyGAEgASgJIj8KFkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USJQoHcHJvbXB0cxgBIAMoCzIULm1lY2F0bC52MS5NY3BQcm9tcHQiuQEKE0dldE1jcFByb21wdFJlcXVlc3QSFwoGc2VydmVyGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESQAoJYXJndW1lbnRzGAMgAygLMi0ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QuQXJndW1lbnRzRW50cnkaMAoOQXJndW1lbnRzRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASIuChBNY3BQcm9tcHRNZXNzYWdlEgwKBHJvbGUYASABKAkSDAoEdGV4dBgCIAEoCSJaChRHZXRNY3BQcm9tcHRSZXNwb25zZRITCgtkZXNjcmlwdGlvbhgBIAEoCRItCghtZXNzYWdlcxgCIAMoCzIbLm1lY2F0bC52MS5NY3BQcm9tcHRNZXNzYWdlIkwKDU1jcFNlcnZlckluZm8SDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSEQoJdHJhbnNwb3J0GAMgASgJEg0KBWdyb3VwGAQgASgJIocBCglNY3BTb3VyY2USDAoEbmFtZRgBIAEoCRIMCgRraW5kGAIgASgJEg8KB2VuYWJsZWQYAyABKAgSDQoFZ3JvdXAYBCABKAkSKQoHc2VydmVycxgFIAMoCzIYLm1lY2F0bC52MS5NY3BTZXJ2ZXJJbmZvEhMKC2RpYWdub3N0aWNzGAYgAygJIhcKFUxpc3RNY3BTb3VyY2VzUmVxdWVzdCJ1ChZMaXN0TWNwU291cmNlc1Jlc3BvbnNlEiUKB3NvdXJjZXMYASADKAsyFC5tZWNhdGwudjEuTWNwU291cmNlEhAKCHJldmlzaW9uGAIgASgEEg0KBXN0YWxlGAMgASgIEhMKC3JlY29uY2lsaW5nGAQgASgIIjcKGFJlZnJlc2hNY3BTb3VyY2VzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIj4KGVJlZnJlc2hNY3BTb3VyY2VzUmVzcG9uc2USEAoIcmV2aXNpb24YASABKAQSDwoHY2hhbmdlZBgCIAEoCCIbChlMaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0IiwKGkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEg4KBmdyb3VwcxgBIAMoCSJ0CglBZ2VudEluZm8SDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVtb2RlbBgDIAEoCRINCgV0b29scxgEIAMoCRIXCg9wZXJtaXNzaW9uX21vZGUYBSABKAkSDQoFY29sb3IYBiABKAkiEwoRTGlzdEFnZW50c1JlcXVlc3QiOgoSTGlzdEFnZW50c1Jlc3BvbnNlEiQKBmFnZW50cxgBIAMoCzIULm1lY2F0bC52MS5BZ2VudEluZm8iLAoHQ29tbWFuZBIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIjIKE0xpc3RDb21tYW5kc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI8ChRMaXN0Q29tbWFuZHNSZXNwb25zZRIkCghjb21tYW5kcxgBIAMoCzISLm1lY2F0bC52MS5Db21tYW5kImkKCFdvcmt0cmVlEhAKCHNlbGVjdG9yGAEgASgJEgwKBGtpbmQYAiABKAkSDQoFbGFiZWwYAyABKAkSDgoGYnJhbmNoGAQgASgJEhAKCHJldmlzaW9uGAUgASgJEgwKBGJhcmUYBiABKAgiMwoUTGlzdFdvcmt0cmVlc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI/ChVMaXN0V29ya3RyZWVzUmVzcG9uc2USJgoJd29ya3RyZWVzGAEgAygLMhMubWVjYXRsLnYxLldvcmt0cmVlInAKCVNraWxsSW5mbxIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEhMKC2FnZW50X293bmVkGAMgASgIEhMKC293bmVyX2FnZW50GAQgASgJEhYKDmFjdGl2ZV92ZXJzaW9uGAUgASgJIhMKEUxpc3RTa2lsbHNSZXF1ZXN0IjoKEkxpc3RTa2lsbHNSZXNwb25zZRIkCgZza2lsbHMYASADKAsyFC5tZWNhdGwudjEuU2tpbGxJbmZvIkEKDVNraWxsRmlsZUluZm8SDAoEbmFtZRgBIAEoCRIMCgRzaXplGAIgASgDEhQKDGluc3RydWN0aW9ucxgDIAEoCCIuChVMaXN0U2tpbGxGaWxlc1JlcXVlc3QSFQoEbmFtZRgBIAEoCUIHukgEcgIQASJBChZMaXN0U2tpbGxGaWxlc1Jlc3BvbnNlEicKBWZpbGVzGAEgAygLMhgubWVjYXRsLnYxLlNraWxsRmlsZUluZm8iRAoUUmVhZFNraWxsRmlsZVJlcXVlc3QSFQoEbmFtZRgBIAEoCUIHukgEcgIQARIVCgRmaWxlGAIgASgJQge6SARyAhABIigKFVJlYWRTa2lsbEZpbGVSZXNwb25zZRIPCgdjb250ZW50GAEgASgJIqEBCghTb3VsSW5mbxIPCgdjb250ZW50GAEgASgJEhIKCnNpemVfYnl0ZXMYAiABKAMSDgoGc2hhMjU2GAMgASgJEg8KB3ByZXNlbnQYBCABKAgSLQoKcHJvdmVuYW5jZRgFIAEoDjIZLm1lY2F0bC52MS5Tb3VsUHJvdmVuYW5jZRIPCgd0cnVzdGVkGAYgASgIEg8KB2RyaWZ0ZWQYByABKAgiEAoOR2V0U291bFJlcXVlc3QiNAoPR2V0U291bFJlc3BvbnNlEiEKBHNvdWwYASABKAsyEy5tZWNhdGwudjEuU291bEluZm8iMgoOVXNlck1vZGVsRW50cnkSCwoDa2V5GAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIiIKE0dldFVzZXJNb2RlbFJlcXVlc3QSCwoDa2V5GAEgASgJIpYCChFVc2VyTW9kZWxSZXZpc2lvbhILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSDwoHdmVyc2lvbhgEIAEoCRIOCgZzdGF0dXMYBSABKAkSDgoGd3JpdGVyGAYgASgJEg4KBm9yaWdpbhgHIAEoCRIZChFzb3VyY2Vfc2Vzc2lvbl9pZBgIIAEoCRIaChJzb3VyY2VfcHJvcG9zYWxfaWQYCSABKAkSLgoKdXBkYXRlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBKBAgKEAtSD3NvdXJjZV9ldmVudF9pZFIRc291cmNlX21lc3NhZ2VfaWQiigEKD1VzZXJNb2RlbERldGFpbBItCgdjdXJyZW50GAEgASgLMhwubWVjYXRsLnYxLlVzZXJNb2RlbFJldmlzaW9uEi0KB2hpc3RvcnkYAiADKAsyHC5tZWNhdGwudjEuVXNlck1vZGVsUmV2aXNpb24SGQoRaGlzdG9yeV9hdmFpbGFibGUYAyABKAgikgEKFEdldFVzZXJNb2RlbFJlc3BvbnNlEioKB2VudHJpZXMYASADKAsyGS5tZWNhdGwudjEuVXNlck1vZGVsRW50cnkSEgoKc2l6ZV9ieXRlcxgCIAEoAxIOCgZzaGEyNTYYAyABKAkSKgoGZGV0YWlsGAQgASgLMhoubWVjYXRsLnYxLlVzZXJNb2RlbERldGFpbCKSAQoJTW9kZWxJbmZvEgoKAmlkGAEgASgJEhMKC3Byb3ZpZGVyX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRINCgVpbWFnZRgEIAEoCBIRCglyZWFzb25pbmcYBSABKAgSFQoNY29udGV4dF9saW1pdBgGIAEoAxIVCg1wcm9tcHRfY2FjaGVkGAcgASgIIhMKEUxpc3RNb2RlbHNSZXF1ZXN0IpsBCg5Qcm92aWRlclN0YXR1cxITCgtwcm92aWRlcl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIMCgRoaW50GAMgASgJEiMKG2RlZmF1bHRfbW9kZWxfYXV0b19zZWxlY3RlZBgEIAEoCBITCgttb2RlbF9jb3VudBgFIAEoBRIdChVhdmFpbGFibGVfbm90X2RlZmF1bHQYBiABKAgibgoSTGlzdE1vZGVsc1Jlc3BvbnNlEiQKBm1vZGVscxgBIAMoCzIULm1lY2F0bC52MS5Nb2RlbEluZm8SMgoPcHJvdmlkZXJfc3RhdHVzGAIgAygLMhkubWVjYXRsLnYxLlByb3ZpZGVyU3RhdHVzIkEKFVJlZmxlY3RTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABSgQIAhADUgVhc3luYyK5AQoRUmVmbGVjdGlvblJlY2VpcHQSFQoNcmVmbGVjdGlvbl9pZBgBIAEoCRITCgtkaXNwb3NpdGlvbhgCIAEoCRIOCgZxdWV1ZWQYAyABKAUSEQoJYWJzdGFpbmVkGAQgASgIEg4KBnN0YWdlZBgFIAEoBRIQCghwcm9tb3RlZBgGIAEoBRISCgpjb25mbGljdGVkGAcgASgFEg4KBnJlYXNvbhgIIAEoCRIPCgdtZXNzYWdlGAkgASgJIkcKFlJlZmxlY3RTZXNzaW9uUmVzcG9uc2USLQoHcmVjZWlwdBgBIAEoCzIcLm1lY2F0bC52MS5SZWZsZWN0aW9uUmVjZWlwdCLxAgoPTGVhcm5pbmdBdHRlbXB0EgoKAmlkGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSDwoHb3V0Y29tZRgEIAEoCRIUCgxmYWlsdXJlX2NvZGUYBSABKAkSGgoSYXR0ZW1wdF9nZW5lcmF0aW9uGAYgASgEEhgKEGNsYWltX2dlbmVyYXRpb24YByABKAQSNAoQY2xhaW1fZXhwaXJlc19hdBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGAoQY2hlY2twb2ludF9zdGFnZRgJIAEoCRITCgtwcm9wb3NhbF9pZBgKIAEoCRIQCghza2lsbF9pZBgLIAEoCRIuCgpjcmVhdGVkX2F0GAwgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA0gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIwChlHZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABIkkKGkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0IksKG0xpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBINCgVzdGF0ZRgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUiYQocTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRIsCghhdHRlbXB0cxgBIAMoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQSEwoLbmV4dF9jdXJzb3IYAiABKAkiVgocTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABIkwKHU11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0Il4KHExpc3RMZWFybmluZ1Byb3Bvc2Fsc1JlcXVlc3QSDgoGc3RhdHVzGAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBRIPCgdwcm9qZWN0GAQgASgJIr4BChNMZWFybmluZ0V2aWRlbmNlUmVmEhIKCnNlc3Npb25faWQYASABKAkSDwoHbG9jYXRvchgCIAEoCRIPCgdvcmRpbmFsGAMgASgFEhEKCWV2ZW50X3NlcRgEIAEoAxIUCgx0b29sX2NhbGxfaWQYBSABKAkSDgoGZGlnZXN0GAYgASgJEhEKCWF2YWlsYWJsZRgHIAEoCBIUCgxhdmFpbGFiaWxpdHkYCCABKAkSDwoHcHJldmlldxgJIAEoCSJnChBMZWFybmluZ0RlY2lzaW9uEgwKBGtpbmQYASABKAkSDQoFYWN0b3IYAiABKAkSDgoGcmVhc29uGAMgASgJEiYKAmF0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCJ5ChhMZWFybmluZ1Byb21vdGlvblJlY2VpcHQSEgoKbWVtb3J5X2tleRgBIAEoCRIXCg9wcmV2aW91c19leGlzdHMYAiABKAgSGAoQcHJldmlvdXNfdmVyc2lvbhgDIAEoCRIWCg5yZXN1bHRfdmVyc2lvbhgEIAEoCSKcBAoQTGVhcm5pbmdQcm9wb3NhbBIKCgJpZBgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEg4KBnN0YXR1cxgDIAEoCRIMCgRraW5kGAQgASgJEgsKA2tleRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtkZXNjcmlwdGlvbhgHIAEoCRINCgV0aXRsZRgIIAEoCRIMCgRib2R5GAkgASgJEjAKCGV2aWRlbmNlGAogAygLMh4ubWVjYXRsLnYxLkxlYXJuaW5nRXZpZGVuY2VSZWYSEAoIdHJpZ2dlcnMYCyADKAkSLgoJZGVjaXNpb25zGAwgAygLMhsubWVjYXRsLnYxLkxlYXJuaW5nRGVjaXNpb24SNgoJcHJvbW90aW9uGA0gASgLMiMubWVjYXRsLnYxLkxlYXJuaW5nUHJvbW90aW9uUmVjZWlwdBIuCgpjcmVhdGVkX2F0GA4gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIWCg5wcm9qZWN0X3Njb3BlZBgQIAEoCBIbChNwcm9tb3Rpb25fYXZhaWxhYmxlGBEgASgIEiQKHHByb21vdGlvbl91bmF2YWlsYWJsZV9yZWFzb24YEiABKAkSGAoQbGVhcm5lZF9za2lsbF9pZBgTIAEoCSJkCh1MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRIuCglwcm9wb3NhbHMYASADKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbBITCgtuZXh0X2N1cnNvchgCIAEoCSJCChpHZXRMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAIgASgJIkwKG0dldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsIpMBCh1EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABEhkKCGRlY2lzaW9uGAMgASgJQge6SARyAhABEg4KBnJlYXNvbhgEIAEoCRIPCgdwcm9qZWN0GAUgASgJIk8KHkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsImcKHFVuZG9MZWFybmluZ1Byb21vdGlvblJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAMgASgJIk4KHVVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwi7AMKE0xlYXJuZWRTa2lsbFZlcnNpb24SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIPCgd2ZXJzaW9uGAMgASgJEhAKCHJldmlzaW9uGAQgASgJEg0KBXN0YXRlGAUgASgJEhMKC293bmVyX2FnZW50GAYgASgJEhMKC2Rlc2NyaXB0aW9uGAcgASgJEgwKBGJvZHkYCCABKAkSEgoKc3VwZXJzZWRlcxgJIAEoCRIWCg5ldmlkZW5jZV9jb3VudBgKIAEoBRIwCghldmlkZW5jZRgLIAMoCzIeLm1lY2F0bC52MS5MZWFybmluZ0V2aWRlbmNlUmVmEi8KC2V2YWx1YXRpb25zGAwgAygLMhoubWVjYXRsLnYxLlNraWxsRXZhbHVhdGlvbhIvCghyZWNlaXB0cxgNIAMoCzIdLm1lY2F0bC52MS5Ta2lsbENoYW5nZVJlY2VpcHQSLgoKY3JlYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgilAEKD1NraWxsRXZhbHVhdGlvbhIPCgd2ZXJkaWN0GAEgASgJEhMKC2ZpeHR1cmVfaWRzGAIgAygJEhAKCGJhc2VsaW5lGAMgASgJEhEKCXRyZWF0bWVudBgEIAEoCRIOCgZyZWFzb24YBSABKAkSJgoCYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIoIDChJTa2lsbENoYW5nZVJlY2VpcHQSCgoCaWQYASABKAkSEAoIc2tpbGxfaWQYAiABKAkSDAoEbmFtZRgDIAEoCRIPCgd2ZXJzaW9uGAQgASgJEhEKCW9wZXJhdGlvbhgFIAEoCRISCgpmcm9tX3N0YXRlGAYgASgJEhAKCHRvX3N0YXRlGAcgASgJEhYKDmV2aWRlbmNlX2NvdW50GAggASgFEhoKEnNvdXJjZV9zZXNzaW9uX2lkcxgJIAMoCRIcChRzb3VyY2VfdG9vbF9jYWxsX2lkcxgKIAMoCRIPCgd2ZXJkaWN0GAsgASgJEhMKC2ZpeHR1cmVfaWRzGAwgAygJEhAKCGJhc2VsaW5lGA0gASgJEhEKCXRyZWF0bWVudBgOIAEoCRImCgJhdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgibgoYTGlzdExlYXJuZWRTa2lsbHNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFEg0KBXN0YXRlGAQgASgJEhMKC293bmVyX2FnZW50GAUgASgJIoUBChlMaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlEi4KBnNraWxscxgBIAMoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhMKC25leHRfY3Vyc29yGAIgASgJEhIKCmdlbmVyYXRpb24YAyABKAQSDwoHcHJvamVjdBgEIAEoCSJtChZHZXRMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESDwoHdmVyc2lvbhgEIAEoCSJtChdHZXRMZWFybmVkU2tpbGxSZXNwb25zZRItCgVza2lsbBgBIAEoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCSKhAQofRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEh0KDGZyb21fdmVyc2lvbhgEIAEoCUIHukgEcgIQARIbCgp0b192ZXJzaW9uGAUgASgJQge6SARyAhABIpEBCiBEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRIMCgRkaWZmGAEgASgJEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCRIQCghza2lsbF9pZBgEIAEoCRIUCgxmcm9tX3ZlcnNpb24YBSABKAkSEgoKdG9fdmVyc2lvbhgGIAEoCSKdAQoZTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEhgKB3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEipwEKGk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEi0KBXNraWxsGAEgASgLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJEhoKEnB1YmxpY2F0aW9uX3N0YXR1cxgEIAEoCRIZChFwdWJsaWNhdGlvbl9lcnJvchgFIAEoCSKmAQobUm9sbGJhY2tMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESHwoOdGFyZ2V0X3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEiSQoXTGlzdFNraWxsQ2hhbmdlc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUihAEKGExpc3RTa2lsbENoYW5nZXNSZXNwb25zZRIuCgdjaGFuZ2VzGAEgAygLMh0ubWVjYXRsLnYxLlNraWxsQ2hhbmdlUmVjZWlwdBITCgtuZXh0X2N1cnNvchgCIAEoCRISCgpnZW5lcmF0aW9uGAMgASgEEg8KB3Byb2plY3QYBCABKAkijwEKEUNyZWF0ZVRlYW1SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEbmFtZRgCIAEoCRIoCgdtZW1iZXJzGAMgAygLMhcubWVjYXRsLnYxLlRlYW1tYXRlU3BlYxIMCgRnb2FsGAQgASgJEhcKD21heF90ZWFtX3Rva2VucxgFIAEoBSJNChJDcmVhdGVUZWFtUmVzcG9uc2USDwoHdGVhbV9pZBgBIAEoCRImCgdtZW1iZXJzGAIgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXIicQoMVGVhbW1hdGVTcGVjEhUKBG5hbWUYASABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgCIAEoCRIMCgRsZWFkGAMgASgIEhAKCG11dGF0aW5nGAQgASgIEhYKDmluaXRpYWxfcHJvbXB0GAUgASgJIpMBChRTcGF3blRlYW1tYXRlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgDIAEoCRIMCgRsZWFkGAQgASgIEhAKCG11dGF0aW5nGAUgASgIEhYKDmluaXRpYWxfcHJvbXB0GAYgASgJIj4KFVNwYXduVGVhbW1hdGVSZXNwb25zZRIlCgZtZW1iZXIYASABKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlciJwChpTZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhMKAnRvGAIgASgJQge6SARyAhABEgwKBGZyb20YAyABKAkSFQoEYm9keRgEIAEoCUIHukgEcgIQASIdChtTZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2UiSgoVQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESFwoGbWVtYmVyGAIgASgJQge6SARyAhABIhgKFkNhbmNlbFRlYW1tYXRlUmVzcG9uc2UiKgoOUnVuVGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASJlCglUZWFtRXZlbnQSDgoGbWVtYmVyGAEgASgJEh8KBWV2ZW50GAIgASgLMhAubWVjYXRsLnYxLkV2ZW50EicKB291dGNvbWUYAyABKAsyFi5tZWNhdGwudjEuVGVhbU91dGNvbWUi2wEKC1RlYW1PdXRjb21lEg4KBnJvdW5kcxgBIAEoBRIRCglxdWllc2NlbnQYAiABKAgSGAoQYnVkZ2V0X2V4aGF1c3RlZBgDIAEoCBIMCgRzdG9wGAQgASgJEh8KBXVzYWdlGAUgASgLMhAubWVjYXRsLnYxLlVzYWdlEjYKDGRpc3Bvc2l0aW9ucxgGIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SKAoIZmluZGluZ3MYByADKAsyFi5tZWNhdGwudjEuVGVhbUZpbmRpbmciKwoPTGlzdFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEicQoQTGlzdFRlYW1SZXNwb25zZRImCgdtZW1iZXJzGAEgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXISIgoFdGFza3MYAiADKAsyEy5tZWNhdGwudjEuVGVhbVRhc2sSEQoJcXVpZXNjZW50GAMgASgIIlEKClRlYW1NZW1iZXISDAoEbmFtZRgBIAEoCRISCgphZ2VudF90eXBlGAIgASgJEg0KBXN0YXRlGAMgASgJEhIKCnNlc3Npb25faWQYBCABKAkiWgoIVGVhbVRhc2sSCgoCaWQYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSEAoIYXNzaWduZWUYBCABKAkSDAoEZGVwcxgFIAMoCSIrCgtUZWFtRmluZGluZxIOCgZtZW1iZXIYASABKAkSDAoEYm9keRgCIAEoCSJ9ChVUZWFtTWVtYmVyRGlzcG9zaXRpb24SDAoEbmFtZRgBIAEoCRIPCgdzdG9wcGVkGAIgASgIEi8KBnJlYXNvbhgDIAEoDjIfLm1lY2F0bC52MS5UZWFtTWVtYmVyU3RvcFJlYXNvbhIUCgxlcnJvcl9yb3VuZHMYBCABKAUiLgoSQ2xlYW51cFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEiFQoTQ2xlYW51cFRlYW1SZXNwb25zZSJvChJBcHByb3ZlUGxhblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIuCgt0YXJnZXRfbW9kZRgCIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIMCgRub3RlGAMgASgJIokBChdNYW51YWxEcmVhbUNhcGFiaWxpdGllcxI4Cg5wcm9qZWN0X21lbW9yeRgBIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkSNAoKdXNlcl9tb2RlbBgCIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkiVQoVRHJlYW1UYXJnZXRDYXBhYmlsaXR5EhAKCGdlbmVyYXRlGAEgASgIEg4KBmRlY2lkZRgCIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAyABKAkiKgoYR2VuZXJhdGVEcmVhbVBsYW5SZXF1ZXN0Eg4KBnRhcmdldBgBIAEoCSJFChlHZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlEigKBHBsYW4YASABKAsyGi5tZWNhdGwudjEuRHJlYW1SZXZpZXdQbGFuIjsKFkRlY2lkZURyZWFtUGxhblJlcXVlc3QSDwoHcGxhbl9pZBgBIAEoCRIQCghkZWNpc2lvbhgCIAEoCSJDChdEZWNpZGVEcmVhbVBsYW5SZXNwb25zZRIoCgdyZWNlaXB0GAEgASgLMhcubWVjYXRsLnYxLkRyZWFtUmVjZWlwdCLLAQoPRHJlYW1SZXZpZXdQbGFuEgoKAmlkGAEgASgJEg4KBnRhcmdldBgCIAEoCRIuCgpleHBpcmVzX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIfChdwbGFubmVkX29wZXJhdGlvbl9jb3VudBgEIAEoBRIcChRwbGFubmVkX3NvdXJjZV9jb3VudBgFIAEoBRItCgpvcGVyYXRpb25zGAYgAygLMhkubWVjYXRsLnYxLkRyZWFtT3BlcmF0aW9uIt8BCg5EcmVhbU9wZXJhdGlvbhIMCgRraW5kGAEgASgJEi0KCHN1cnZpdm9yGAIgASgLMhsubWVjYXRsLnYxLkRyZWFtUGFydGljaXBhbnQSLAoHc291cmNlcxgDIAMoCzIbLm1lY2F0bC52MS5EcmVhbVBhcnRpY2lwYW50EjAKC3JlcGxhY2VtZW50GAQgASgLMhsubWVjYXRsLnYxLkRyZWFtUmVwbGFjZW1lbnQSDgoGcmVhc29uGAUgASgJEiAKGGV4YWN0X2R1cGxpY2F0ZV9lbGlnaWJsZRgGIAEoCCJDChBEcmVhbVBhcnRpY2lwYW50EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCSI2ChBEcmVhbVJlcGxhY2VtZW50Eg0KBXZhbHVlGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJItcBCgxEcmVhbVJlY2VpcHQSCgoCaWQYASABKAkSDgoGdGFyZ2V0GAIgASgJEhMKC2Rpc3Bvc2l0aW9uGAMgASgJEhwKFHBsYW5uZWRfc291cmNlX2NvdW50GAQgASgFEhwKFGFwcGxpZWRfc291cmNlX2NvdW50GAUgASgFEh8KF2NvbmZsaWN0ZWRfc291cmNlX2NvdW50GAYgASgFEhwKFHNraXBwZWRfc291cmNlX2NvdW50GAcgASgFEhsKE2ZhaWxlZF9zb3VyY2VfY291bnQYCCABKAUiNAoVQ29tcGFjdFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiKwoWQ29tcGFjdFNlc3Npb25SZXNwb25zZRIRCgljb21wYWN0ZWQYASABKAgiNwohV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkiTgohV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSFQoNZW5yb2xsbWVudF9pZBgCIAEoCSJxChNXb3Jrc3BhY2VFbnJvbGxtZW50EhUKDWVucm9sbG1lbnRfaWQYASABKAkSDgoGc3RhdHVzGAIgASgJEhkKEXJlcXVpcmVkX3NlcnZpY2VzGAMgASgNEhgKEHByZXNlbnRhdGlvbl91cmwYBCABKAkqvgEKDlBlcm1pc3Npb25Nb2RlEh8KG1BFUk1JU1NJT05fTU9ERV9VTlNQRUNJRklFRBAAEhsKF1BFUk1JU1NJT05fTU9ERV9ERUZBVUxUEAESGAoUUEVSTUlTU0lPTl9NT0RFX1BMQU4QAhIgChxQRVJNSVNTSU9OX01PREVfQUNDRVBUX0VESVRTEAMSGAoUUEVSTUlTU0lPTl9NT0RFX0FVVE8QBBIYChRQRVJNSVNTSU9OX01PREVfWU9MTxAFKpIBCg9BcHByb3ZhbFZlcmRpY3QSIAocQVBQUk9WQUxfVkVSRElDVF9VTlNQRUNJRklFRBAAEhkKFUFQUFJPVkFMX1ZFUkRJQ1RfREVOWRABEh8KG0FQUFJPVkFMX1ZFUkRJQ1RfQUxMT1dfT05DRRACEiEKHUFQUFJPVkFMX1ZFUkRJQ1RfQUxMT1dfQUxXQVlTEAMqvgEKDFN0ZWVyT3V0Y29tZRIdChlTVEVFUl9PVVRDT01FX1VOU1BFQ0lGSUVEEAASGgoWU1RFRVJfT1VUQ09NRV9BQ0NFUFRFRBABEhoKFlNURUVSX09VVENPTUVfQVBQRU5ERUQQAhIbChdTVEVFUl9PVVRDT01FX1JFVFJBQ1RFRBADEh4KGlNURUVSX09VVENPTUVfTk9ORV9QRU5ESU5HEAQSGgoWU1RFRVJfT1VUQ09NRV9UT09fTEFURRAFKoABCgxHdWFyZHJhaWxKb2ISHQoZR1VBUkRSQUlMX0pPQl9VTlNQRUNJRklFRBAAEhgKFEdVQVJEUkFJTF9KT0JfQUNUSU9OEAESGQoVR1VBUkRSQUlMX0pPQl9JTkJPVU5EEAISHAoYR1VBUkRSQUlMX0pPQl9QRVJNSVNTSU9OEAMqqgEKE0d1YXJkcmFpbEFzc2Vzc21lbnQSJAogR1VBUkRSQUlMX0FTU0VTU01FTlRfVU5TUEVDSUZJRUQQABIjCh9HVUFSRFJBSUxfQVNTRVNTTUVOVF9BQ0NFUFRBQkxFEAESIwofR1VBUkRSQUlMX0FTU0VTU01FTlRfUFJPSElCSVRFRBACEiMKH0dVQVJEUkFJTF9BU1NFU1NNRU5UX1VOUkVTT0xWRUQQAyqMAQoTR3VhcmRyYWlsSW5zcGVjdGlvbhIkCiBHVUFSRFJBSUxfSU5TUEVDVElPTl9VTlNQRUNJRklFRBAAEiEKHUdVQVJEUkFJTF9JTlNQRUNUSU9OX0NPTVBMRVRFEAESLAooR1VBUkRSQUlMX0lOU1BFQ1RJT05fT1BFUkFUSU9OQUxfRkFJTFVSRRACKtACChRHdWFyZHJhaWxEaXNwb3NpdGlvbhIlCiFHVUFSRFJBSUxfRElTUE9TSVRJT05fVU5TUEVDSUZJRUQQABIhCh1HVUFSRFJBSUxfRElTUE9TSVRJT05fRVhFQ1VURRABEiQKIEdVQVJEUkFJTF9ESVNQT1NJVElPTl9BU0tfQUNUSU9OEAISKQolR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1dJVEhIT0xEX1JFU1VMVBADEigKJEdVQVJEUkFJTF9ESVNQT1NJVElPTl9SRUxFQVNFX1JFU1VMVBAEEh4KGkdVQVJEUkFJTF9ESVNQT1NJVElPTl9ERU5ZEAUSJwojR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1BBU1NfQURWSVNPUlkQBhIqCiZHVUFSRFJBSUxfRElTUE9TSVRJT05fQ09OVElOVUVfV0FSTklORxAHKpABChVHdWFyZHJhaWxBcHByb3ZhbEtpbmQSJwojR1VBUkRSQUlMX0FQUFJPVkFMX0tJTkRfVU5TUEVDSUZJRUQQABIiCh5HVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9BQ1RJT04QARIqCiZHVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9SRVNVTFRfUkVMRUFTRRACKpgBCgxIb29rRGVjaXNpb24SHQoZSE9PS19ERUNJU0lPTl9VTlNQRUNJRklFRBAAEhYKEkhPT0tfREVDSVNJT05fSU5GTxABEhkKFUhPT0tfREVDSVNJT05fQkxPQ0tFRBACEhoKFkhPT0tfREVDSVNJT05fTU9ESUZJRUQQAxIaChZIT09LX0RFQ0lTSU9OX0FEVklTT1JZEAQqlgEKEFJldHJ5RGlzcG9zaXRpb24SIQodUkVUUllfRElTUE9TSVRJT05fVU5TUEVDSUZJRUQQABIdChlSRVRSWV9ESVNQT1NJVElPTl9VTktOT1dOEAESHwobUkVUUllfRElTUE9TSVRJT05fUkVUUllBQkxFEAISHwobUkVUUllfRElTUE9TSVRJT05fUEVSTUFORU5UEAMqqAEKDlN0cmVhbVByb2dyZXNzEh8KG1NUUkVBTV9QUk9HUkVTU19VTlNQRUNJRklFRBAAEhsKF1NUUkVBTV9QUk9HUkVTU19VTktOT1dOEAESHQoZU1RSRUFNX1BST0dSRVNTX1BSRUNPTU1JVBACEhsKF1NUUkVBTV9QUk9HUkVTU19WSVNJQkxFEAMSHAoYU1RSRUFNX1BST0dSRVNTX0NPTVBMRVRFEAQqhAEKDlNvdWxQcm92ZW5hbmNlEh8KG1NPVUxfUFJPVkVOQU5DRV9VTlNQRUNJRklFRBAAEhgKFFNPVUxfUFJPVkVOQU5DRV9VU0VSEAESGwoXU09VTF9QUk9WRU5BTkNFX1BST0pFQ1QQAhIaChZTT1VMX1BST1ZFTkFOQ0VfRFJJVkVSEAMqrQEKFFRlYW1NZW1iZXJTdG9wUmVhc29uEicKI1RFQU1fTUVNQkVSX1NUT1BfUkVBU09OX1VOU1BFQ0lGSUVEEAASIQodVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fRVJST1IQARIlCiFURUFNX01FTUJFUl9TVE9QX1JFQVNPTl9DQU5DRUxMRUQQAhIiCh5URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9CVURHRVQQAzKcOQoOSGFybmVzc1NlcnZpY2USZwoUR2V0Q29tcGF0aWJpbGl0eUluZm8SJi5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0GicubWVjYXRsLnYxLkdldENvbXBhdGliaWxpdHlJbmZvUmVzcG9uc2USbQoWTGlzdEV4ZWN1dGlvblRlbXBsYXRlcxIoLm1lY2F0bC52MS5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdBopLm1lY2F0bC52MS5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USUgoNQ3JlYXRlU2Vzc2lvbhIfLm1lY2F0bC52MS5DcmVhdGVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5DcmVhdGVTZXNzaW9uUmVzcG9uc2USUgoNR2V0U2VydmVySW5mbxIfLm1lY2F0bC52MS5HZXRTZXJ2ZXJJbmZvUmVxdWVzdBogLm1lY2F0bC52MS5HZXRTZXJ2ZXJJbmZvUmVzcG9uc2USSQoKR2V0U2Vzc2lvbhIcLm1lY2F0bC52MS5HZXRTZXNzaW9uUmVxdWVzdBodLm1lY2F0bC52MS5HZXRTZXNzaW9uUmVzcG9uc2USagoVTGlzdEd1YXJkcmFpbENvdmVyYWdlEicubWVjYXRsLnYxLkxpc3RHdWFyZHJhaWxDb3ZlcmFnZVJlcXVlc3QaKC5tZWNhdGwudjEuTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVzcG9uc2UScwoYR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsEioubWVjYXRsLnYxLkdldEd1YXJkcmFpbFJldmlld0RldGFpbFJlcXVlc3QaKy5tZWNhdGwudjEuR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVzcG9uc2USZwoUR2V0U2Vzc2lvblRyYW5zY3JpcHQSJi5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXF1ZXN0GicubWVjYXRsLnYxLkdldFNlc3Npb25UcmFuc2NyaXB0UmVzcG9uc2USQAoHU2V0TW9kZRIZLm1lY2F0bC52MS5TZXRNb2RlUmVxdWVzdBoaLm1lY2F0bC52MS5TZXRNb2RlUmVzcG9uc2USTwoMQ2xvc2VTZXNzaW9uEh4ubWVjYXRsLnYxLkNsb3NlU2Vzc2lvblJlcXVlc3QaHy5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVzcG9uc2USUgoNUmVuYW1lU2Vzc2lvbhIfLm1lY2F0bC52MS5SZW5hbWVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5SZW5hbWVTZXNzaW9uUmVzcG9uc2USUgoNRGVsZXRlU2Vzc2lvbhIfLm1lY2F0bC52MS5EZWxldGVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5EZWxldGVTZXNzaW9uUmVzcG9uc2USVQoOQ29tcGFjdFNlc3Npb24SIC5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXF1ZXN0GiEubWVjYXRsLnYxLkNvbXBhY3RTZXNzaW9uUmVzcG9uc2USTwoMQ2xlYXJTZXNzaW9uEh4ubWVjYXRsLnYxLkNsZWFyU2Vzc2lvblJlcXVlc3QaHy5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVzcG9uc2USTAoLRm9ya1Nlc3Npb24SHS5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXF1ZXN0Gh4ubWVjYXRsLnYxLkZvcmtTZXNzaW9uUmVzcG9uc2USRwoIQ29udmVyc2USGi5tZWNhdGwudjEuQ29udmVyc2VSZXF1ZXN0GhsubWVjYXRsLnYxLkNvbnZlcnNlUmVzcG9uc2UoATABElIKDVJlc29sdmVSdW5Bc2sSHy5tZWNhdGwudjEuUmVzb2x2ZVJ1bkFza1JlcXVlc3QaIC5tZWNhdGwudjEuUmVzb2x2ZVJ1bkFza1Jlc3BvbnNlElUKDlJlc29sdmVQbGFuQXNrEiAubWVjYXRsLnYxLlJlc29sdmVQbGFuQXNrUmVxdWVzdBohLm1lY2F0bC52MS5SZXNvbHZlUGxhbkFza1Jlc3BvbnNlEkYKCUNhbmNlbFJ1bhIbLm1lY2F0bC52MS5DYW5jZWxSdW5SZXF1ZXN0GhwubWVjYXRsLnYxLkNhbmNlbFJ1blJlc3BvbnNlEkMKCFN0ZWVyUnVuEhoubWVjYXRsLnYxLlN0ZWVyUnVuUmVxdWVzdBobLm1lY2F0bC52MS5TdGVlclJ1blJlc3BvbnNlElUKDkNhbmNlbFJ1blN0ZWVyEiAubWVjYXRsLnYxLkNhbmNlbFJ1blN0ZWVyUmVxdWVzdBohLm1lY2F0bC52MS5DYW5jZWxSdW5TdGVlclJlc3BvbnNlElsKEExpc3RNY3BSZXNvdXJjZXMSIi5tZWNhdGwudjEuTGlzdE1jcFJlc291cmNlc1JlcXVlc3QaIy5tZWNhdGwudjEuTGlzdE1jcFJlc291cmNlc1Jlc3BvbnNlElgKD1JlYWRNY3BSZXNvdXJjZRIhLm1lY2F0bC52MS5SZWFkTWNwUmVzb3VyY2VSZXF1ZXN0GiIubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlc3BvbnNlElUKDkxpc3RNY3BQcm9tcHRzEiAubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0TWNwUHJvbXB0c1Jlc3BvbnNlEk8KDEdldE1jcFByb21wdBIeLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlc3BvbnNlElUKDkxpc3RNY3BTb3VyY2VzEiAubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0TWNwU291cmNlc1Jlc3BvbnNlEl4KEVJlZnJlc2hNY3BTb3VyY2VzEiMubWVjYXRsLnYxLlJlZnJlc2hNY3BTb3VyY2VzUmVxdWVzdBokLm1lY2F0bC52MS5SZWZyZXNoTWNwU291cmNlc1Jlc3BvbnNlEnMKGExpc3RTZXNzaW9uTWNwQ29ubmVjdG9ycxIqLm1lY2F0bC52MS5MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXF1ZXN0GisubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1Jlc3BvbnNlEmEKEkxpc3RUb29sSGl2ZUdyb3VwcxIkLm1lY2F0bC52MS5MaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0GiUubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEkkKCkxpc3RBZ2VudHMSHC5tZWNhdGwudjEuTGlzdEFnZW50c1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdEFnZW50c1Jlc3BvbnNlEk8KDExpc3RDb21tYW5kcxIeLm1lY2F0bC52MS5MaXN0Q29tbWFuZHNSZXF1ZXN0Gh8ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1Jlc3BvbnNlElIKDUxpc3RXb3JrdHJlZXMSHy5tZWNhdGwudjEuTGlzdFdvcmt0cmVlc1JlcXVlc3QaIC5tZWNhdGwudjEuTGlzdFdvcmt0cmVlc1Jlc3BvbnNlElAKE1N0cmVhbVNlc3Npb25FdmVudHMSJS5tZWNhdGwudjEuU3RyZWFtU2Vzc2lvbkV2ZW50c1JlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJMChFTdHJlYW1TZXNzaW9uTGl2ZRIjLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uTGl2ZVJlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJjChJXYXRjaFNlc3Npb25FdmVudHMSJC5tZWNhdGwudjEuV2F0Y2hTZXNzaW9uRXZlbnRzUmVxdWVzdBolLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXNwb25zZTABEogBCh9HZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uEjEubWVjYXRsLnYxLkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXF1ZXN0GjIubWVjYXRsLnYxLkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRJ0ChdSZWNoZWNrTWNwQXV0aG9yaXphdGlvbhIpLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlcXVlc3QaKi5tZWNhdGwudjEuUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAEScQoWQ2FuY2VsTWNwQXV0aG9yaXphdGlvbhIoLm1lY2F0bC52MS5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVxdWVzdBopLm1lY2F0bC52MS5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVzcG9uc2UoATABEk8KDExpc3RTZXNzaW9ucxIeLm1lY2F0bC52MS5MaXN0U2Vzc2lvbnNSZXF1ZXN0Gh8ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1Jlc3BvbnNlElsKEEdldFN0b3JhZ2VIZWFsdGgSIi5tZWNhdGwudjEuR2V0U3RvcmFnZUhlYWx0aFJlcXVlc3QaIy5tZWNhdGwudjEuR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEmEKElBsYW5TZXNzaW9uQ2xlYW51cBIkLm1lY2F0bC52MS5QbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0GiUubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlc3BvbnNlElMKE0FwcGx5U2Vzc2lvbkNsZWFudXASJS5tZWNhdGwudjEuQXBwbHlTZXNzaW9uQ2xlYW51cFJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJVChRDYW5jZWxTZXNzaW9uQ2xlYW51cBImLm1lY2F0bC52MS5DYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJVChRHZXRTZXNzaW9uQ2xlYW51cEpvYhImLm1lY2F0bC52MS5HZXRTZXNzaW9uQ2xlYW51cEpvYlJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJJCgpMaXN0U2tpbGxzEhwubWVjYXRsLnYxLkxpc3RTa2lsbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RTa2lsbHNSZXNwb25zZRJVCg5MaXN0U2tpbGxGaWxlcxIgLm1lY2F0bC52MS5MaXN0U2tpbGxGaWxlc1JlcXVlc3QaIS5tZWNhdGwudjEuTGlzdFNraWxsRmlsZXNSZXNwb25zZRJSCg1SZWFkU2tpbGxGaWxlEh8ubWVjYXRsLnYxLlJlYWRTa2lsbEZpbGVSZXF1ZXN0GiAubWVjYXRsLnYxLlJlYWRTa2lsbEZpbGVSZXNwb25zZRJACgdHZXRTb3VsEhkubWVjYXRsLnYxLkdldFNvdWxSZXF1ZXN0GhoubWVjYXRsLnYxLkdldFNvdWxSZXNwb25zZRJPCgxHZXRVc2VyTW9kZWwSHi5tZWNhdGwudjEuR2V0VXNlck1vZGVsUmVxdWVzdBofLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXNwb25zZRJVCg5SZWZsZWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuUmVmbGVjdFNlc3Npb25SZXNwb25zZRJhChJHZXRMZWFybmluZ0F0dGVtcHQSJC5tZWNhdGwudjEuR2V0TGVhcm5pbmdBdHRlbXB0UmVxdWVzdBolLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJnChRMaXN0TGVhcm5pbmdBdHRlbXB0cxImLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1JlcXVlc3QaJy5tZWNhdGwudjEuTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRJpChRSZXRyeUxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmsKFkFiYW5kb25MZWFybmluZ0F0dGVtcHQSJy5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBooLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJeChFHZW5lcmF0ZURyZWFtUGxhbhIjLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlcXVlc3QaJC5tZWNhdGwudjEuR2VuZXJhdGVEcmVhbVBsYW5SZXNwb25zZRJYCg9EZWNpZGVEcmVhbVBsYW4SIS5tZWNhdGwudjEuRGVjaWRlRHJlYW1QbGFuUmVxdWVzdBoiLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXNwb25zZRJqChVMaXN0TGVhcm5pbmdQcm9wb3NhbHMSJy5tZWNhdGwudjEuTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVxdWVzdBooLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRJkChNHZXRMZWFybmluZ1Byb3Bvc2FsEiUubWVjYXRsLnYxLkdldExlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0GiYubWVjYXRsLnYxLkdldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRJtChZEZWNpZGVMZWFybmluZ1Byb3Bvc2FsEigubWVjYXRsLnYxLkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0GikubWVjYXRsLnYxLkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRJqChVVbmRvTGVhcm5pbmdQcm9tb3Rpb24SJy5tZWNhdGwudjEuVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVxdWVzdBooLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXNwb25zZRJeChFMaXN0TGVhcm5lZFNraWxscxIjLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1JlcXVlc3QaJC5tZWNhdGwudjEuTGlzdExlYXJuZWRTa2lsbHNSZXNwb25zZRJYCg9HZXRMZWFybmVkU2tpbGwSIS5tZWNhdGwudjEuR2V0TGVhcm5lZFNraWxsUmVxdWVzdBoiLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXNwb25zZRJzChhEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnMSKi5tZWNhdGwudjEuRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBorLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRJjChRBY3RpdmF0ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmEKElJlamVjdExlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmIKE0FyY2hpdmVMZWFybmVkU2tpbGwSJC5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJlChRSb2xsYmFja0xlYXJuZWRTa2lsbBImLm1lY2F0bC52MS5Sb2xsYmFja0xlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USWwoQTGlzdFNraWxsQ2hhbmdlcxIiLm1lY2F0bC52MS5MaXN0U2tpbGxDaGFuZ2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0U2tpbGxDaGFuZ2VzUmVzcG9uc2USSQoKTGlzdE1vZGVscxIcLm1lY2F0bC52MS5MaXN0TW9kZWxzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0TW9kZWxzUmVzcG9uc2USSQoKQ3JlYXRlVGVhbRIcLm1lY2F0bC52MS5DcmVhdGVUZWFtUmVxdWVzdBodLm1lY2F0bC52MS5DcmVhdGVUZWFtUmVzcG9uc2USUgoNU3Bhd25UZWFtbWF0ZRIfLm1lY2F0bC52MS5TcGF3blRlYW1tYXRlUmVxdWVzdBogLm1lY2F0bC52MS5TcGF3blRlYW1tYXRlUmVzcG9uc2USZAoTU2VuZFRlYW1tYXRlTWVzc2FnZRIlLm1lY2F0bC52MS5TZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBomLm1lY2F0bC52MS5TZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2USVQoOQ2FuY2VsVGVhbW1hdGUSIC5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0GiEubWVjYXRsLnYxLkNhbmNlbFRlYW1tYXRlUmVzcG9uc2USPAoHUnVuVGVhbRIZLm1lY2F0bC52MS5SdW5UZWFtUmVxdWVzdBoULm1lY2F0bC52MS5UZWFtRXZlbnQwARJDCghMaXN0VGVhbRIaLm1lY2F0bC52MS5MaXN0VGVhbVJlcXVlc3QaGy5tZWNhdGwudjEuTGlzdFRlYW1SZXNwb25zZRJMCgtDbGVhbnVwVGVhbRIdLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlcXVlc3QaHi5tZWNhdGwudjEuQ2xlYW51cFRlYW1SZXNwb25zZRJACgtBcHByb3ZlUGxhbhIdLm1lY2F0bC52MS5BcHByb3ZlUGxhblJlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJoChhDb25uZWN0V29ya3NwYWNlU2VydmljZXMSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaAoYUmV0cnlXb3Jrc3BhY2VFbnJvbGxtZW50EiwubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRDb250cm9sUmVxdWVzdBoeLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50EmkKGUNhbmNlbFdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRCogEKDWNvbS5tZWNhdGwudjFCDEhhcm5lc3NQcm90b1ABWj5naXRodWIuY29tL3N0YWNrbG9rL21lY2F0bC9jb250cmFjdHMvZ2VuL2dvL21lY2F0bC92MTttZWNhdGx2MaICA01YWKoCCU1lY2F0bC5WMcoCCU1lY2F0bFxWMeICFU1lY2F0bFxWMVxHUEJNZXRhZGF0YeoCCk1lY2F0bDo6VjFiBnByb3RvMw", [file_buf_validate_validate, file_google_protobuf_timestamp]); /** * Limits are the configured stop conditions for a session. A zero value in @@ -2391,6 +2391,9 @@ export type SetModeRequest = Message<"mecatl.v1.SetModeRequest"> & { /** * mode is the desired permission posture; unspecified defaults to DEFAULT. + * AUTO requires an enforcing guardrails checker; the server rejects SetMode + * to AUTO without one. The server may also enforce a MaxAllowedMode ceiling; + * requesting a mode above it is rejected with INVALID_ARGUMENT. * * @generated from field: mecatl.v1.PermissionMode mode = 2; */ @@ -10462,7 +10465,8 @@ export const WorkspaceEnrollmentSchema: GenMessage = /*@__P /** * PermissionMode is the session-wide permission posture, mirroring * session.PermissionMode. Plan mode exposes a read-only toolset; acceptEdits - * auto-accepts edits. + * auto-accepts edits; auto runs autonomously with an enforcing guardrails + * checker; yolo runs gate-free with no enforcing checker. * * @generated from enum mecatl.v1.PermissionMode */ @@ -10494,6 +10498,23 @@ export enum PermissionMode { * @generated from enum value: PERMISSION_MODE_ACCEPT_EDITS = 3; */ ACCEPT_EDITS = 3, + + /** + * PERMISSION_MODE_AUTO runs autonomously using an enforcing guardrails checker. + * Entering this mode requires a checker; the server rejects SetMode to AUTO + * without one. + * + * @generated from enum value: PERMISSION_MODE_AUTO = 4; + */ + AUTO = 4, + + /** + * PERMISSION_MODE_YOLO runs gate-free with no enforcing checker. Advisory + * monitoring may remain. Configured deny rules still apply. + * + * @generated from enum value: PERMISSION_MODE_YOLO = 5; + */ + YOLO = 5, } /** From e6557ee3a4d7e791caf484cf9aae03134def280a Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Wed, 14 Oct 2026 20:19:19 +0300 Subject: [PATCH 19/48] fix(mecatui): wire auto/yolo modes end-to-end in the UI ModeFromString and ModeString now handle PERMISSION_MODE_AUTO and PERMISSION_MODE_YOLO so the UI renders 'auto'/'yolo' instead of falling through to 'default'. PermissionModeVocabulary uses the correct session mode strings for those two entries. modeLabel no longer says 'posture X stays until restart' when cycling to a lower-ceiling mode: allow-all is mode-driven now, so switching from yolo to default is fully effective and nothing stays. postureSummary describes the server ceiling and trust floor rather than claiming allow-all is always on at auto/yolo posture. Co-authored-by: Mecatl --- cmd/mecatui/client/client.go | 8 +++++ cmd/mecatui/ui/builtins.go | 29 +++++++++++++------ cmd/mecatui/ui/help.go | 4 +-- cmd/mecatui/ui/mode_cycle.go | 9 +++--- .../ui/permission_mode_vocabulary_test.go | 4 ++- cmd/mecatui/ui/posture_badge_test.go | 10 ++++--- 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/cmd/mecatui/client/client.go b/cmd/mecatui/client/client.go index df51237d25..df8a382126 100644 --- a/cmd/mecatui/client/client.go +++ b/cmd/mecatui/client/client.go @@ -714,6 +714,10 @@ func ModeFromString(s string) mecatlv1.PermissionMode { return mecatlv1.PermissionMode_PERMISSION_MODE_ACCEPT_EDITS case ModeDefaultString, "": return mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT + case "auto": + return mecatlv1.PermissionMode_PERMISSION_MODE_AUTO + case "yolo": + return mecatlv1.PermissionMode_PERMISSION_MODE_YOLO default: return mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED } @@ -738,6 +742,10 @@ func ModeString(m mecatlv1.PermissionMode) string { return modePlanString case mecatlv1.PermissionMode_PERMISSION_MODE_ACCEPT_EDITS: return "accept-edits" + case mecatlv1.PermissionMode_PERMISSION_MODE_AUTO: + return "auto" + case mecatlv1.PermissionMode_PERMISSION_MODE_YOLO: + return "yolo" case mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT, mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED: return ModeDefaultString default: diff --git a/cmd/mecatui/ui/builtins.go b/cmd/mecatui/ui/builtins.go index a84c363d7f..24758ea1df 100644 --- a/cmd/mecatui/ui/builtins.go +++ b/cmd/mecatui/ui/builtins.go @@ -638,12 +638,18 @@ func (m Model) runDebugAsk() (tea.Model, tea.Cmd) { } // postureSummary renders the one-line /posture summary for a posture token. It is -// pure (no Model) so it is directly testable. allow-all + main-substitution are on at -// auto+yolo; the CHILD substitution (prompt-injection defense OFF) is yolo-only; -// project-trust is on at trusted+. An empty/unknown token degrades to a bare label. +// pure (no Model) so it is directly testable. +// +// Posture sets the server ceiling (which modes a session may enter) and the +// project-trust floor. Allow-all and substitution loosening are now session-mode +// behaviors: auto/yolo sessions inject the allow-all rule per-evaluate, so the +// description names the ceiling rather than claiming allow-all is always on. +// Project-trust is raised for trusted+ on interactive roots. An empty/unknown +// token degrades to a bare label. func postureSummary(p string) string { - allowAll := p == postureAuto || p == postureYolo - childDefenseOff := p == postureYolo + ceilingAuto := p == postureAuto + ceilingYolo := p == postureYolo + childDefenseOff := p == postureYolo // yolo session mode loosens child substitution trust := p == postureTrusted || p == postureAuto || p == postureYolo onoff := func(b bool) string { if b { @@ -655,12 +661,17 @@ func postureSummary(p string) string { if label == "" { label = unknownLabel } + ceiling := "default/plan/accept-edits" + if ceilingYolo { + ceiling = "all modes including yolo" + } else if ceilingAuto { + ceiling = "up to and including auto" + } return "posture " + label + - " — allow-all " + onoff(allowAll) + - "; main $()/heredoc auto-run " + onoff(allowAll) + - "; child $()/heredoc auto-run (injection-defense off) " + onoff(childDefenseOff) + + " — ceiling " + ceiling + + "; child $()/heredoc auto-run when in yolo mode (injection-defense off) " + onoff(childDefenseOff) + "; project-trust " + onoff(trust) + - " (Deny & configured Ask always apply)" + " (allow-all is mode-driven: auto/yolo sessions inject it; Deny & configured Ask always apply)" } type builtinName struct { diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 59c16ea676..4749cf0922 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -330,8 +330,8 @@ func PermissionModeVocabulary() []PermissionModeEntry { {Name: "plan", Posture: postureStrict, SessionMode: "plan"}, {Name: "default", Posture: postureStrict, SessionMode: client.ModeDefaultString}, {Name: "accept-edits", Posture: postureStrict, SessionMode: "accept-edits"}, - {Name: "auto", Posture: postureAuto, SessionMode: client.ModeDefaultString}, - {Name: "yolo", Posture: postureYolo, SessionMode: client.ModeDefaultString}, + {Name: "auto", Posture: postureAuto, SessionMode: "auto"}, + {Name: "yolo", Posture: postureYolo, SessionMode: "yolo"}, } } diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go index 5e543337e2..b48538c4f9 100644 --- a/cmd/mecatui/ui/mode_cycle.go +++ b/cmd/mecatui/ui/mode_cycle.go @@ -195,12 +195,11 @@ func (m Model) renderModeBlocked() string { return style.Render(strings.Join(lines, "\n")) } -// modeLabel names a landed mode for the footer. A mode below the running -// posture applies only its session half, so the label says the posture stays. +// modeLabel names a landed mode for the footer. All modes at or below the +// server ceiling are fully effective — allow-all and loose-substitution are +// session-mode-driven, not posture-driven, so switching to a lower mode +// actually changes behavior and nothing "stays until restart". func (m Model) modeLabel(e PermissionModeEntry) string { - if postureRank(e.Posture) < postureRank(m.caps.Posture) { - return e.Name + " · posture " + m.caps.Posture + " stays until restart" - } return e.Name } diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index 669db1fc6d..cbb465f874 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -139,7 +139,9 @@ func TestModeSwitchUnderTrustedPosture(t *testing.T) { // auto and yolo raise posture above trusted → blocked (need restart). {token: "auto", blocked: true, status: []string{"auto needs a guardrails checker", "esc back to accept-edits"}}, {token: "yolo", blocked: true, status: []string{"yolo needs a guardrails checker"}}, - {token: "default", setMode: true, status: []string{"mode default · posture trusted stays until restart"}}, + // In the new architecture, switching to a lower-ceiling mode is fully effective: + // the session mode drives allow-all, so "posture stays" no longer applies. + {token: "default", setMode: true, status: []string{"mode default"}}, {token: "plan", setMode: true}, }) want := []string{"plan", "accept-edits", "default", "plan"} diff --git a/cmd/mecatui/ui/posture_badge_test.go b/cmd/mecatui/ui/posture_badge_test.go index 01555e74e2..f3ee766649 100644 --- a/cmd/mecatui/ui/posture_badge_test.go +++ b/cmd/mecatui/ui/posture_badge_test.go @@ -257,10 +257,12 @@ func TestPostureSummary(t *testing.T) { posture string want []string // substrings that MUST be present }{ - {"strict", []string{"posture strict", "allow-all off", "child $()/heredoc auto-run (injection-defense off) off", "project-trust off"}}, - {"trusted", []string{"posture trusted", "allow-all off", "project-trust on"}}, - {"auto", []string{"posture auto", "allow-all on", "main $()/heredoc auto-run on", "child $()/heredoc auto-run (injection-defense off) off", "project-trust on"}}, - {"yolo", []string{"posture yolo", "allow-all on", "child $()/heredoc auto-run (injection-defense off) on", "project-trust on"}}, + // allow-all is now session-mode-driven (not posture-driven), so the summary + // names the ceiling and trust, not an always-on allow-all flag. + {"strict", []string{"posture strict", "ceiling default/plan/accept-edits", "project-trust off", "allow-all is mode-driven"}}, + {"trusted", []string{"posture trusted", "project-trust on"}}, + {"auto", []string{"posture auto", "ceiling up to and including auto", "child $()/heredoc auto-run when in yolo mode (injection-defense off) off", "project-trust on"}}, + {"yolo", []string{"posture yolo", "ceiling all modes including yolo", "child $()/heredoc auto-run when in yolo mode (injection-defense off) on", "project-trust on"}}, } for _, tc := range cases { got := postureSummary(tc.posture) From b84175bccf4355a8c5738be003e19bc6566758ca Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Wed, 14 Oct 2026 20:40:02 +0300 Subject: [PATCH 20/48] fix(mecatui): correct auto/yolo mode display and remove stale 'pending' suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four UI bugs introduced by the mode-driven architecture: 1. ModeFromString/ModeString did not handle 'auto'/'yolo', mapping them to UNSPECIFIED → 'default'. Fixed: they now round-trip correctly through PERMISSION_MODE_AUTO/YOLO. 2. PermissionModeVocabulary set auto/yolo SessionMode to 'default' (the old token convention). Fixed: they now carry 'auto'/'yolo' so acceptedModeToken matches correctly when a session is in those modes. 3. modeLabel showed 'posture X stays until restart' when cycling to a lower-ceiling mode. In the new architecture the mode is fully effective (allow-all is mode-driven); removed the stale branch. 4. headerMode added ' pending' even when pendingMode == activeMode, meaning cycling through modes and returning to the starting auto mode would show 'auto pending' despite the session already being confirmed in auto. Fixed: skip the suffix when pending == active (the in-flight call is a no-op confirmation, not a genuine transition). Co-authored-by: Mecatl --- cmd/mecatui/ui/mode_cycle.go | 12 +++- .../ui/permission_mode_vocabulary_test.go | 72 +++++++++++++------ 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go index b48538c4f9..0a3bbf9314 100644 --- a/cmd/mecatui/ui/mode_cycle.go +++ b/cmd/mecatui/ui/mode_cycle.go @@ -108,6 +108,14 @@ func (m Model) cycleMode() (tea.Model, tea.Cmd) { // headerMode is the session mode the header shows: the mode the cycle landed // on when it did, else the session's mode, marked blocked or pending. +// +// "pending" means a SetMode round-trip is in flight. When the pending mode +// equals the server-confirmed active mode (m.pendingMode == m.activeMode) the +// session IS already in the target mode; the in-flight call is a no-op +// confirmation. Showing "pending" in that case is misleading — e.g. cycling +// through other modes and back to the starting auto mode would flash +// "auto pending" even though the session never left auto from the user's +// perspective. Skip the suffix in that case. func (m Model) headerMode() string { mode := m.activeMode if mode == "" { @@ -122,7 +130,9 @@ func (m Model) headerMode() string { switch { case m.modeBlocked(): mode += modeBlockedSuffix - case m.pendingMode != "": + case m.pendingMode != "" && m.pendingMode != m.activeMode: + // Only show "pending" when the in-flight mode differs from what the + // server has already confirmed — a genuine transition, not a no-op. mode += " pending" } return mode diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index cbb465f874..bca916b538 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -262,12 +262,13 @@ func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { // The token table, written out independently of PermissionModeVocabulary. // 5-token vocabulary: trusted and trusted-accept-edits removed. + // auto and yolo sessions start in their own named modes, not "default". want := []struct{ token, posture, session string }{ {"plan", "strict", "plan"}, {"default", "strict", "default"}, {"accept-edits", "strict", "accept-edits"}, - {"auto", "auto", "default"}, - {"yolo", "yolo", "default"}, + {"auto", "auto", "auto"}, + {"yolo", "yolo", "yolo"}, } for _, w := range want { row := "posture " + w.posture + " (process-wide) · new sessions start in " + w.session @@ -331,35 +332,55 @@ func TestHeaderShowsPostureWhenAboveStrict(t *testing.T) { } } -// TestHeaderKeepsPostureAcrossModeCycle pins that under auto, cycling -// through yolo (which needs a restart), default, plan, and accept-edits keeps the -// auto badge on every frame, including the pending frame before the server +// TestHeaderKeepsPostureAcrossModeCycle pins that under auto, cycling through +// yolo (blocked: above the auto ceiling), then through lower modes keeps the +// auto badge on every frame, including the pending frames before the server // confirms each switch. +// +// A session on an auto-posture server starts in "auto" mode. The cycle order +// from "auto" is: yolo (blocked) → default → plan → accept-edits → auto → … +// Yolo is the only mode that needs a restart; every other landing sends a +// SetMode and shows "pending" until the server confirms. func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { - conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := permissionModeTestModel(t, conv, postureAuto, true) + // Session starts in "auto" mode — the natural default on an auto-posture server. + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "auto"} + m := newTestModelFromDeps(Deps{ + Session: conv, + Conv: conv, + Theme: theme.New("aztec", theme.AztecPalette()), + Mode: "auto", + Embedded: true, + Ctx: context.Background(), + }) + m = applyAll(m, + tea.WindowSizeMsg{Width: 140, Height: 30}, + client.SessionReadyMsg{SessionID: "sess-auto-cycle", Mode: "auto", Capabilities: client.Capabilities{Posture: postureAuto}}, + ) + assertAuto := func(step, wantMode string) { t.Helper() header := stripANSIstr(m.renderHeader()) if !strings.Contains(header, autoBadgeText) { - t.Fatalf("%s: header lost the auto posture: %q", step, header) + t.Fatalf("%s: header lost the auto posture badge: %q", step, header) } if got := statusMode(m); got != wantMode { - t.Fatalf("%s: status mode = %q, want %s", step, got, wantMode) + t.Fatalf("%s: status mode = %q, want %q", step, got, wantMode) } } - assertAuto("start", "default") - // yolo needs a restart, and default is the session half auto already runs: - // neither press needs a server round trip. - for _, step := range []struct{ token, header string }{{"yolo", "yolo blocked"}, {"default", "default"}} { - mm, cmd := m.Update(modeKey()) - m = mm.(Model) - if cmd != nil { - t.Fatalf("landing on %s issued a command", step.token) - } - assertAuto("landed "+step.token, step.header) + assertAuto("start", "auto") + + // yolo is above the auto ceiling → blocked, no server round trip. + mm, cmd := m.Update(modeKey()) + m = mm.(Model) + if cmd != nil { + t.Fatalf("landing on yolo issued a command: should be blocked, not switched") } - for _, next := range []string{"plan", "accept-edits"} { + assertAuto("landed yolo", "yolo blocked") + + // Switching to modes below auto (default, plan, accept-edits) all require + // a SetMode round trip: the session is in "auto", switching to anything lower + // is a genuine change. + for _, next := range []string{"default", "plan", "accept-edits"} { mm, cmd := m.Update(modeKey()) m = mm.(Model) if cmd == nil { @@ -369,6 +390,17 @@ func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { m = applyAll(m, cmd()) assertAuto("confirmed "+next, next) } + + // Cycling back to auto from accept-edits: pendingMode="auto" != activeMode="accept-edits" + // → genuine transition, shows "auto pending" until server confirms. + mm, cmd = m.Update(modeKey()) + m = mm.(Model) + if cmd == nil { + t.Fatalf("cycling back to auto issued no command") + } + assertAuto("pending auto", "auto pending") + m = applyAll(m, cmd()) + assertAuto("confirmed auto", "auto") } // TestHelpOverlayNamesWhoseRestart pins that the embedded server's From 825a6bd983bf182abb1145c1c5b8a6d4fe698bb2 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Wed, 14 Oct 2026 21:46:56 +0300 Subject: [PATCH 21/48] fix(lint,api,docs): fix gci ordering, unused receiver, goconst, api snapshot, grpc ref lint fixes (from this PR's changes): - gci: reformat import groups in internal/app/allowall_test.go, build.go, permission_mode_test.go, posture_test.go - revive: modeLabel receiver is unused after body simplified to 'return e.Name'; rename to Model (blank receiver) - goconst: postureReplacementToken used string literal 'auto'/'yolo'; use p.String() to avoid the constant violation api: run task api:update to record ModeAuto and ModeYolo in engine/api/session.txt; add engine/CHANGELOG.md entry (Added/minor). docs: run task docs:grpc-ref to regenerate grpc-schema.md with the two new PermissionMode enum values. Co-authored-by: Mecatl --- cmd/mecated/permission_mode.go | 11 +++++------ cmd/mecatui/ui/mode_cycle.go | 2 +- engine/CHANGELOG.md | 7 +++++++ engine/api/session.txt | 2 ++ internal/app/allowall_test.go | 2 +- internal/app/build.go | 5 ++--- internal/app/permission_mode_test.go | 1 - internal/app/posture_test.go | 8 ++++---- user-docs/reference/grpc-schema.md | 7 +++++-- 9 files changed, 27 insertions(+), 18 deletions(-) diff --git a/cmd/mecated/permission_mode.go b/cmd/mecated/permission_mode.go index a53a40a727..676391ccb2 100644 --- a/cmd/mecated/permission_mode.go +++ b/cmd/mecated/permission_mode.go @@ -60,13 +60,12 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { // postureReplacementToken names the token that replaces a legacy --posture value. // auto and yolo are their own tokens; the strict-posture tiers map to "default". func postureReplacementToken(raw string) string { - switch app.ParsePosture(raw) { - case app.PostureAuto: - return "auto" - case app.PostureYolo: - return "yolo" + p := app.ParsePosture(raw) + switch p { + case app.PostureAuto, app.PostureYolo: + return p.String() // "auto" or "yolo", matching the token name } - if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { + if tok, ok := app.PermissionModeForPair(p, session.ModeDefault); ok { return tok.Name } return "default" diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go index 0a3bbf9314..aad7fbb5b2 100644 --- a/cmd/mecatui/ui/mode_cycle.go +++ b/cmd/mecatui/ui/mode_cycle.go @@ -209,7 +209,7 @@ func (m Model) renderModeBlocked() string { // server ceiling are fully effective — allow-all and loose-substitution are // session-mode-driven, not posture-driven, so switching to a lower mode // actually changes behavior and nothing "stays until restart". -func (m Model) modeLabel(e PermissionModeEntry) string { +func (Model) modeLabel(e PermissionModeEntry) string { return e.Name } diff --git a/engine/CHANGELOG.md b/engine/CHANGELOG.md index c8146473d6..e327f00257 100644 --- a/engine/CHANGELOG.md +++ b/engine/CHANGELOG.md @@ -21,6 +21,13 @@ The covered surface is the eight core packages (`session`, `governance`, `learni fingerprint is inferred from effective values or inherited by successors. Added (minor). +- **`ModeAuto` and `ModeYolo` permission modes** — adds `session.ModeAuto = "auto"` + and `session.ModeYolo = "yolo"` to `session.PermissionMode`. These complete the + five-mode vocabulary (`plan`, `default`, `acceptEdits`, `auto`, `yolo`) that the + unified permission-mode architecture requires; `Policy.Evaluate` now injects + allow-all and loose-substitution at evaluation time based on the session's current + mode, so mode switches are fully effective at runtime. Added (minor). + - **Schedule-store claim and retry conformance** — adds `scheduleconformance.RunClaimAndRetryConformance` with the complete shared suite plus unresolved prior-claim rejection, late-result isolation, and diff --git a/engine/api/session.txt b/engine/api/session.txt index 6c67f21c2b..d53ac74949 100644 --- a/engine/api/session.txt +++ b/engine/api/session.txt @@ -184,8 +184,10 @@ const MaxToolResultTextBytes untyped int = 25600 const MediaAudio MediaKind = "audio" const MediaImage MediaKind = "image" const ModeAccept PermissionMode = "acceptEdits" +const ModeAuto PermissionMode = "auto" const ModeDefault PermissionMode = "default" const ModePlan PermissionMode = "plan" +const ModeYolo PermissionMode = "yolo" const NoProgressExtractiveNudgeText untyped string = "Stop investigating now and do not run any more commands or tools. Using only the information you have already gathered, write your best final answer to the original task as a direct message now, even if it is incomplete or uncertain — note any gaps briefly. Do not plan further steps; deliver what you have." const NoProgressNudgeText untyped string = "Please continue. Make concrete progress on the task using your tools, or — if you are blocked or believe the task is complete — say so explicitly in a short message." const ParallelBranchEnd ParallelEventKind = "branch_end" diff --git a/internal/app/allowall_test.go b/internal/app/allowall_test.go index a3575a691d..3d2b0d6520 100644 --- a/internal/app/allowall_test.go +++ b/internal/app/allowall_test.go @@ -276,7 +276,7 @@ func TestSubstitutionLooseningIsModeDriven(t *testing.T) { want want }{ {session.ModeDefault, want{governance.Ask, governance.Ask}}, - {session.ModeAuto, want{governance.Ask, governance.Ask}}, // auto: standard evaluator, substitution floor stands + {session.ModeAuto, want{governance.Ask, governance.Ask}}, // auto: standard evaluator, substitution floor stands {session.ModeYolo, want{governance.Allow, governance.Allow}}, // yolo: evalLoose, substitution allowed } for _, tc := range cases { diff --git a/internal/app/build.go b/internal/app/build.go index 121df18554..14577029fd 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -2463,8 +2463,8 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { DefaultMode: cfg.DefaultSessionMode, MaxAllowedMode: cfg.MaxAllowedMode, EnforcingCheckerConfigured: checker == checkerEnforcing, - BuildID: buildinfo.BuildID, - ServerImplementation: cfg.ServerImplementation, + BuildID: buildinfo.BuildID, + ServerImplementation: cfg.ServerImplementation, // GetServerInfo looks up only a caller-selected, already-known provider // in this immutable composition registry. It intentionally does not // inspect session selectors, discover providers, or re-read configuration. @@ -9769,7 +9769,6 @@ func defaultRules() []governance.Rule { } } - // mainRules returns the main engine's static ruleset. The built-in mutate-ask // floor (defaultRules) applies to all modes; auto/yolo allow-all is injected // at evaluation time by Policy.Evaluate based on the session's current mode, diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index cc2e2e1c65..f1d21b02d7 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -110,7 +110,6 @@ func TestTrustedKeepsCurrentMeaning(t *testing.T) { } } - func TestAllowAllTokenRequiresChecker(t *testing.T) { // The checker gate is now a runtime WARN, not a startup refusal. // Build succeeds; entering auto mode without a checker is refused at SetMode time. diff --git a/internal/app/posture_test.go b/internal/app/posture_test.go index 1c1c3324dc..e5e9c8d4d9 100644 --- a/internal/app/posture_test.go +++ b/internal/app/posture_test.go @@ -95,8 +95,8 @@ func TestPostureResolutionTable(t *testing.T) { } }{ {"headless", true, []struct { - name string - posture Posture + name string + posture Posture trustFlag, trusted bool }{ {"strict+no-trust", PostureStrict, false, false}, @@ -109,8 +109,8 @@ func TestPostureResolutionTable(t *testing.T) { {"yolo+trust", PostureYolo, true, true}, }}, {"interactive", false, []struct { - name string - posture Posture + name string + posture Posture trustFlag, trusted bool }{ {"strict+no-trust", PostureStrict, false, false}, diff --git a/user-docs/reference/grpc-schema.md b/user-docs/reference/grpc-schema.md index 669aba5908..e37d5ffca9 100644 --- a/user-docs/reference/grpc-schema.md +++ b/user-docs/reference/grpc-schema.md @@ -3245,7 +3245,7 @@ SetModeRequest changes a session's permission posture. | Field | Type | Label | Oneof | Description | |---|---|---|---|---| | `session_id` | `string` | | | session_id is the session to update. | -| `mode` | `PermissionMode` | | | mode is the desired permission posture; unspecified defaults to DEFAULT. | +| `mode` | `PermissionMode` | | | mode is the desired permission posture; unspecified defaults to DEFAULT. AUTO requires an enforcing guardrails checker; the server rejects SetMode to AUTO without one. The server may also enforce a MaxAllowedMode ceiling; requesting a mode above it is rejected with INVALID_ARGUMENT. | @@ -4104,7 +4104,8 @@ its prose. PermissionMode is the session-wide permission posture, mirroring session.PermissionMode. Plan mode exposes a read-only toolset; acceptEdits -auto-accepts edits. +auto-accepts edits; auto runs autonomously with an enforcing guardrails +checker; yolo runs gate-free with no enforcing checker. | Name | Number | Description | |---|---|---| @@ -4112,6 +4113,8 @@ auto-accepts edits. | `PERMISSION_MODE_DEFAULT` | `1` | PERMISSION_MODE_DEFAULT is the standard deny -> ask -> allow posture. | | `PERMISSION_MODE_PLAN` | `2` | PERMISSION_MODE_PLAN enforces a read-only toolset. | | `PERMISSION_MODE_ACCEPT_EDITS` | `3` | PERMISSION_MODE_ACCEPT_EDITS auto-accepts edits. | +| `PERMISSION_MODE_AUTO` | `4` | PERMISSION_MODE_AUTO runs autonomously using an enforcing guardrails checker. Entering this mode requires a checker; the server rejects SetMode to AUTO without one. | +| `PERMISSION_MODE_YOLO` | `5` | PERMISSION_MODE_YOLO runs gate-free with no enforcing checker. Advisory monitoring may remain. Configured deny rules still apply. | #### `mecatl.v1.RetryDisposition` From de15fd0d910aa728b317cd5cdb8228504e2757e4 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Thu, 15 Oct 2026 15:40:35 +0300 Subject: [PATCH 22/48] fix(permissions): make auto/yolo modes work end to end and split trust from mode Server - Map PERMISSION_MODE_AUTO/YOLO in the gRPC and HTTP mode mappers; they previously collapsed to default, so --permission-mode auto started in default and SetMode(auto) never confirmed. - Share one mode-admission check (ceiling + enforcing checker for auto) across CreateSession, SetMode, and schedule fires; the operator's configured default mode stays admissible. ApprovePlan refuses auto/yolo targets instead of silently denying. - Strict tokens share the accept-edits ceiling, so default/plan servers can still enter accept-edits. - Guardrail demotion to advisory is per session mode: only yolo-mode sessions are advisory, so an auto session on a yolo server keeps an enforcing checker (promoted to a per-session engine). - Add optional ServerCapabilities.project_trusted carrying the effective project-trust decision. mecatui - A SetMode refusal at idle clears "pending" and reports the server reason; a mismatched reply adopts the server's mode; the cycle continues past a refused mode instead of trapping on it. - The top-right badge shows project trust (trusted/untrusted), not the posture; the yolo mode segment renders the red YOLO pill (new StatusML `danger` token), with the bolt on emoji-capable terminals (Terminal.Emoji, status protocol v6). API compatibility: additive. AUTO/YOLO were already in the enum; a client that sent them now gets that mode or an InvalidArgument refusal instead of a silent default session. ApprovePlan with an auto/yolo target is refused (previously allow-once into default); no shipped client sends it. project_trusted is a new optional field; older servers leave it unset and the client shows no trust badge. No major bump. Co-authored-by: Mecatl --- cmd/mecatui/client/capabilities.go | 28 +- cmd/mecatui/client/session.go | 12 + cmd/mecatui/customization/command_test.go | 8 +- cmd/mecatui/customization/defaults.go | 11 +- cmd/mecatui/customization/input.go | 6 +- cmd/mecatui/customization/statusml.go | 7 +- cmd/mecatui/ui/builtins.go | 12 +- cmd/mecatui/ui/canonical_status_test.go | 18 +- cmd/mecatui/ui/mode_cycle.go | 6 +- cmd/mecatui/ui/mode_test.go | 81 + cmd/mecatui/ui/model.go | 3 + .../ui/permission_mode_vocabulary_test.go | 45 +- cmd/mecatui/ui/posture_badge_test.go | 257 +- cmd/mecatui/ui/statusline.go | 7 + cmd/mecatui/ui/statusline_source.go | 2 +- cmd/mecatui/ui/statusline_test.go | 60 +- cmd/mecatui/ui/update.go | 18 +- cmd/mecatui/ui/view.go | 74 +- contracts/gen/go/mecatl/v1/harness.pb.go | 6269 +++++++++-------- contracts/proto/mecatl/v1/harness.proto | 11 +- internal/adapter/server/http.go | 4 + internal/adapter/server/mapper.go | 8 + .../adapter/server/mode_admission_test.go | 245 + internal/adapter/server/service.go | 42 +- internal/app/build.go | 13 +- internal/app/guardrails.go | 20 +- .../app/guardrails_approve_once_e2e_test.go | 36 + internal/app/permission_mode.go | 29 +- internal/app/permission_mode_test.go | 8 + internal/app/posture_build_test.go | 40 + internal/app/slots.go | 22 +- .../src/gen/mecatl/v1/harness_pb.ts | 18 +- .../permissions-and-posture.md | 17 +- user-docs/mecatui/status-line.md | 10 +- user-docs/reference/grpc-schema.md | 3 +- user-docs/reference/server-cli.md | 22 +- 36 files changed, 3963 insertions(+), 3509 deletions(-) create mode 100644 internal/adapter/server/mode_admission_test.go diff --git a/cmd/mecatui/client/capabilities.go b/cmd/mecatui/client/capabilities.go index 0eb3a962ac..29d3f58cec 100644 --- a/cmd/mecatui/client/capabilities.go +++ b/cmd/mecatui/client/capabilities.go @@ -43,10 +43,12 @@ type Capabilities struct { Image bool Audio bool // Posture is the SERVER-WIDE operator posture tier ("strict"/"trusted"/"auto"/ - // "yolo"), CHROME ONLY: the ui renders a "⚠ auto"/"⚠ yolo" badge so an operator - // sees the daemon's automation posture. NOT session state. Empty (an older server, - // or strict/trusted) → no badge. + // "yolo"). It bounds which modes the ui's mode cycle may switch to. NOT + // session state. Empty on an older server. Posture string + // ProjectTrust is "trusted" or "untrusted" for the server's launch + // workspace, CHROME ONLY: the ui's header badge. Empty on an older server. + ProjectTrust string // Worktrees is true when a WorktreeLister is wired (ListWorktrees may return a // non-empty list for a real git repo). It gates the /worktrees overlay — the // first-class operator workflow for binding a session to an EXISTING sibling @@ -130,6 +132,7 @@ func capabilitiesFrom(c *mecatlv1.ServerCapabilities) Capabilities { Image: c.GetImage(), Audio: c.GetAudio(), Posture: c.GetPosture(), + ProjectTrust: projectTrustFrom(c), Worktrees: c.GetWorktrees(), Scheduling: c.GetScheduling(), Reflection: c.GetReflection(), @@ -146,6 +149,25 @@ func capabilitiesFrom(c *mecatlv1.ServerCapabilities) Capabilities { } } +// Project-trust spellings for Capabilities.ProjectTrust. +const ( + ProjectTrusted = "trusted" + ProjectUntrusted = "untrusted" +) + +// projectTrustFrom maps the optional project_trusted echo; unset (an older +// server) stays "" so the client shows no trust indicator. +func projectTrustFrom(c *mecatlv1.ServerCapabilities) string { + switch { + case c.ProjectTrusted == nil: + return "" + case c.GetProjectTrusted(): + return ProjectTrusted + default: + return ProjectUntrusted + } +} + func manualDreamCapabilitiesFrom(c *mecatlv1.ManualDreamCapabilities) *ManualDreamCapabilities { if c == nil { return nil diff --git a/cmd/mecatui/client/session.go b/cmd/mecatui/client/session.go index 278b2c29c7..32170c609f 100644 --- a/cmd/mecatui/client/session.go +++ b/cmd/mecatui/client/session.go @@ -2,9 +2,11 @@ package client import ( "context" + "errors" "fmt" tea "charm.land/bubbletea/v2" + grpcstatus "google.golang.org/grpc/status" mecatlv1 "github.com/stacklok/mecatl/contracts/gen/go/mecatl/v1" ) @@ -144,6 +146,16 @@ func (c *Client) SetMode(ctx context.Context, id, mode string) (string, error) { return snapshotFrom(resp.GetSession()).Mode, nil } +// ModeErrorText is the server's reason for a failed SetMode, without the +// transport framing, falling back to the whole error. +func ModeErrorText(err error) string { + var se interface{ GRPCStatus() *grpcstatus.Status } + if errors.As(err, &se) { + return se.GRPCStatus().Message() + } + return err.Error() +} + // ResolvedModelMsg carries the result of a GetSession refetch (the footer // context-meter heal, issue #66, the plan-approval mode+model refresh, // issue #206, and the caps-heal path for /sessions continue + /effort fork, diff --git a/cmd/mecatui/customization/command_test.go b/cmd/mecatui/customization/command_test.go index 297879df43..77aa284be8 100644 --- a/cmd/mecatui/customization/command_test.go +++ b/cmd/mecatui/customization/command_test.go @@ -251,7 +251,7 @@ func TestStatusLineCommandDoesNotTrimNonASCIIOutputBoundary(t *testing.T) { } } -func TestStatusInputProtocolV5WorkspacePathNameAndContext(t *testing.T) { +func TestStatusInputProtocolV6WorkspacePathNameAndContext(t *testing.T) { input := Input{ Version: ProtocolVersion, Context: Context{ @@ -263,14 +263,14 @@ func TestStatusInputProtocolV5WorkspacePathNameAndContext(t *testing.T) { }, Model: Model{ProviderID: "openai", ID: "gpt-5", ProviderLabel: "openai/gpt-5", FriendlyName: "GPT-5"}, Workspace: Workspace{Location: "local", Name: "provider label", Path: "/eligible/root"}, - Terminal: Terminal{FooterAvailCols: 80}, + Terminal: Terminal{FooterAvailCols: 80, Emoji: true}, } wire, err := json.Marshal(input) if err != nil { t.Fatalf("marshal status input: %v", err) } - if ProtocolVersion != 5 || !strings.Contains(string(wire), `"Model":{"ProviderID":"openai","ID":"gpt-5","ProviderLabel":"openai/gpt-5","FriendlyName":"GPT-5","Route":""`) || strings.Contains(string(wire), "DisplayName") || !strings.Contains(string(wire), `"Name":"provider label"`) || !strings.Contains(string(wire), `"Path":"/eligible/root"`) || !strings.Contains(string(wire), `"Context":{"Used":{"Raw":75,"Human":"75"},"Window":{"Raw":100,"Human":"100"},"Percent":75,"Known":true,"Estimated":true}`) || strings.Contains(string(wire), "Basename") { - t.Fatalf("status input v5 workspace/context projection = %s", wire) + if ProtocolVersion != 6 || !strings.Contains(string(wire), `"FooterAvailCols":80,"Emoji":true`) || !strings.Contains(string(wire), `"Model":{"ProviderID":"openai","ID":"gpt-5","ProviderLabel":"openai/gpt-5","FriendlyName":"GPT-5","Route":""`) || strings.Contains(string(wire), "DisplayName") || !strings.Contains(string(wire), `"Name":"provider label"`) || !strings.Contains(string(wire), `"Path":"/eligible/root"`) || !strings.Contains(string(wire), `"Context":{"Used":{"Raw":75,"Human":"75"},"Window":{"Raw":100,"Human":"100"},"Percent":75,"Known":true,"Estimated":true}`) || strings.Contains(string(wire), "Basename") { + t.Fatalf("status input v6 workspace/context/terminal projection = %s", wire) } templates := NewTemplateSource(TemplateSet{Footer: SurfaceTemplates{Full: `
[{{.Workspace.Path}}]
`}}, 0) t.Cleanup(func() { _ = templates.Close(context.Background()) }) diff --git a/cmd/mecatui/customization/defaults.go b/cmd/mecatui/customization/defaults.go index 11b54a1602..0071fc5c15 100644 --- a/cmd/mecatui/customization/defaults.go +++ b/cmd/mecatui/customization/defaults.go @@ -1,13 +1,20 @@ package customization +// modeSegmentTemplate is the header's permission-mode segment. The yolo mode is +// marked with the alarm pill (the danger token, its text carrying the pill's +// padding), preceded by a ⚡️ bolt outside the pill on an emoji-capable +// terminal; every other mode, including a pending or blocked yolo, is plain +// warning text. +const modeSegmentTemplate = `{{if .Session.Mode}} · mode {{if eq .Session.Mode "yolo"}}{{if .Terminal.Emoji}}⚡️ {{end}} YOLO {{else}}{{.Session.Mode}}{{end}}{{end}}` + // defaultTemplateSet contains the status and terminal-title templates shipped // with mecatui. Keep these defaults together so every presentation surface has // one canonical source. func defaultTemplateSet() TemplateSet { return TemplateSet{ Header: SurfaceTemplates{ - Full: `
mecatui{{if .Session.Title}} · {{elide 32 .Session.Title}}{{end}}{{if .Model.ProviderLabel}} · {{.Model.ProviderLabel}}{{if .Model.Route}}/{{.Model.Route}}{{end}}{{end}}{{if .Session.Mode}} · mode {{.Session.Mode}}{{end}}{{if and (eq .Server.ConnectionMode "connect") .Server.DisplayTarget}} · {{.Server.DisplayTarget}}{{end}}
`, - Compact: `
mecatui{{if .Session.Title}} · {{elide 24 .Session.Title}}{{end}}{{if .Model.ProviderLabel}} · {{.Model.ProviderLabel}}{{end}}{{if .Session.Mode}} · mode {{.Session.Mode}}{{end}}
`, + Full: `
mecatui{{if .Session.Title}} · {{elide 32 .Session.Title}}{{end}}{{if .Model.ProviderLabel}} · {{.Model.ProviderLabel}}{{if .Model.Route}}/{{.Model.Route}}{{end}}{{end}}` + modeSegmentTemplate + `{{if and (eq .Server.ConnectionMode "connect") .Server.DisplayTarget}} · {{.Server.DisplayTarget}}{{end}}
`, + Compact: `
mecatui{{if .Session.Title}} · {{elide 24 .Session.Title}}{{end}}{{if .Model.ProviderLabel}} · {{.Model.ProviderLabel}}{{end}}` + modeSegmentTemplate + `
`, Minimal: `
mecatui{{if .Session.Title}} · {{elide 12 .Session.Title}}{{end}}
`, }, Footer: SurfaceTemplates{ diff --git a/cmd/mecatui/customization/input.go b/cmd/mecatui/customization/input.go index 25b9505b2a..c204152513 100644 --- a/cmd/mecatui/customization/input.go +++ b/cmd/mecatui/customization/input.go @@ -130,12 +130,16 @@ type Workspace struct { // Terminal provides measured dimensions and independently reserved columns for // status surfaces. Cols is the full terminal width. HeaderAvailCols and // FooterAvailCols are the widths remaining after the renderer reserves mandatory -// header safety/navigation and footer activity lanes, respectively. +// header safety/navigation and footer activity lanes, respectively. Emoji +// reports whether the terminal is likely to render emoji presentation (for +// example ⚡️) at its expected width; it is a conservative, environment-based +// guess fixed for the process. type Terminal struct { Rows int Cols int HeaderAvailCols int FooterAvailCols int + Emoji bool } // MainAgent carries the main agent's display-safe activity. State is one of diff --git a/cmd/mecatui/customization/statusml.go b/cmd/mecatui/customization/statusml.go index dff7a2dce1..1c7e65035f 100644 --- a/cmd/mecatui/customization/statusml.go +++ b/cmd/mecatui/customization/statusml.go @@ -12,7 +12,7 @@ import ( const ( // ProtocolVersion is the current Input wire-independent contract version. - ProtocolVersion uint8 = 5 + ProtocolVersion uint8 = 6 maxMarkupBytes = 16 << 10 maxSpanRunes = 4 << 10 @@ -34,6 +34,9 @@ const ( TokenWarning Token = "warning" TokenError Token = "error" TokenInfo Token = "info" + // TokenDanger renders as the filled, theme-independent alarm pill (the yolo + // mode marker) rather than a foreground colour. + TokenDanger Token = "danger" ) // Palette resolves a StatusML semantic token through the active theme. It @@ -267,7 +270,7 @@ func validName(name string) bool { func isToken(name string) bool { switch Token(name) { - case TokenText, TokenMuted, TokenPrimary, TokenSecondary, TokenAccent, TokenSuccess, TokenWarning, TokenError, TokenInfo: + case TokenText, TokenMuted, TokenPrimary, TokenSecondary, TokenAccent, TokenSuccess, TokenWarning, TokenError, TokenInfo, TokenDanger: return true default: return false diff --git a/cmd/mecatui/ui/builtins.go b/cmd/mecatui/ui/builtins.go index 24758ea1df..6335ccb2f4 100644 --- a/cmd/mecatui/ui/builtins.go +++ b/cmd/mecatui/ui/builtins.go @@ -587,7 +587,7 @@ func (m Model) runLearningSensitivity() (tea.Model, tea.Cmd) { // non-empty. The summary names the four defenses the posture controls so an operator // can confirm, e.g., that the child prompt-injection defense is OFF under yolo. func (m Model) runPosture() (tea.Model, tea.Cmd) { - base := postureSummary(m.caps.Posture) + base := postureSummary(m.caps.Posture, m.caps.ProjectTrust) if m.deps.Guardrails == nil || m.sessionID == "" { m.statusMsg = m.deps.Theme.Style("muted").Render(base + "; checker unknown (server does not expose guardrail coverage)") return m, nil @@ -644,13 +644,17 @@ func (m Model) runDebugAsk() (tea.Model, tea.Cmd) { // project-trust floor. Allow-all and substitution loosening are now session-mode // behaviors: auto/yolo sessions inject the allow-all rule per-evaluate, so the // description names the ceiling rather than claiming allow-all is always on. -// Project-trust is raised for trusted+ on interactive roots. An empty/unknown -// token degrades to a bare label. -func postureSummary(p string) string { +// Project-trust is the server-reported trust when known (trust), else inferred +// from the posture, which raises it for trusted+ on interactive roots. An +// empty/unknown token degrades to a bare label. +func postureSummary(p, projectTrust string) string { ceilingAuto := p == postureAuto ceilingYolo := p == postureYolo childDefenseOff := p == postureYolo // yolo session mode loosens child substitution trust := p == postureTrusted || p == postureAuto || p == postureYolo + if projectTrust != "" { + trust = projectTrust == client.ProjectTrusted + } onoff := func(b bool) string { if b { return "on" diff --git a/cmd/mecatui/ui/canonical_status_test.go b/cmd/mecatui/ui/canonical_status_test.go index aaff471425..fe90dd844e 100644 --- a/cmd/mecatui/ui/canonical_status_test.go +++ b/cmd/mecatui/ui/canonical_status_test.go @@ -57,7 +57,7 @@ func TestCanonicalStatus_Scenario1_StockSourceOwnsSurfaces(t *testing.T) { func TestCanonicalStatus_Scenario1_EmptySourceDoesNotFallBack(t *testing.T) { source := &statusSourceFake{changed: make(chan struct{}, 1)} m := canonicalFrame(source, 110) - m.caps.Posture = postureAuto + m.caps.ProjectTrust = client.ProjectUntrusted m.generatedStatusLine = customization.Result{Header: customization.Surface{Present: true, Spans: []customization.Span{{Text: strings.Repeat("oversize", 100)}}}, Footer: customization.Surface{Present: true, Spans: []customization.Span{{Text: strings.Repeat("oversize", 100)}}}} for _, result := range []customization.Result{m.generatedStatusLine, {}, {Header: customization.Surface{Present: true}, Footer: customization.Surface{Present: true}}} { m.generatedStatusLine = result @@ -65,7 +65,7 @@ func TestCanonicalStatus_Scenario1_EmptySourceDoesNotFallBack(t *testing.T) { if strings.Contains(header, "session") || strings.Contains(header, "canonical-model") || strings.Contains(header, "oversize") || strings.Contains(header, "·") || strings.Contains(footer, "ctx") || strings.Contains(footer, "oversize") { t.Fatalf("source fallback: %q / %q", header, footer) } - if !strings.Contains(header, "auto") || !strings.Contains(footer, "ready") || !strings.Contains(footer, "help") { + if !strings.Contains(header, client.ProjectUntrusted) || !strings.Contains(footer, "ready") || !strings.Contains(footer, "help") { t.Fatalf("lost mandatory chrome: %q / %q", header, footer) } } @@ -73,7 +73,7 @@ func TestCanonicalStatus_Scenario1_EmptySourceDoesNotFallBack(t *testing.T) { func TestCanonicalStatus_Scenario1_NoSourceMinimalIdentity(t *testing.T) { m := canonicalFrame(nil, 110) - m.caps.Posture = postureAuto + m.caps.ProjectTrust = client.ProjectUntrusted for _, id := range []string{"", "safe-1234567890", "hostile\x1b[31m\nmore-1234567890", "\xff"} { m.sessionID = id header, footer := stripANSIstr(m.renderHeader()), stripANSIstr(m.renderFooter()) @@ -84,7 +84,7 @@ func TestCanonicalStatus_Scenario1_NoSourceMinimalIdentity(t *testing.T) { } else if !strings.Contains(header, "session "+handle) { t.Fatalf("known identity: %q", header) } - if strings.Contains(header, "canonical-model") || strings.Contains(header, "[31m") || strings.Contains(footer, "ctx") || strings.Contains(footer, "↑") || !strings.Contains(header, "auto") || !strings.Contains(footer, "ready") || !strings.Contains(footer, "help") { + if strings.Contains(header, "canonical-model") || strings.Contains(header, "[31m") || strings.Contains(footer, "ctx") || strings.Contains(footer, "↑") || !strings.Contains(header, client.ProjectUntrusted) || !strings.Contains(footer, "ready") || !strings.Contains(footer, "help") { t.Fatalf("unsafe/legacy identity or lost chrome: %q / %q", header, footer) } } @@ -196,10 +196,10 @@ func TestCanonicalStatus_Scenario2_DebugDisclosureSurvivesMissingSourceAndFatal( func TestCanonicalStatus_Scenario2_DebugCommandSourceReceivesReservedWidth(t *testing.T) { m := canonicalFrame(nil, 120) m.deps.DebugTarget = "target-1234567890" - m.caps.Posture = postureAuto + m.caps.ProjectTrust = client.ProjectUntrusted m.conv.recordFileChange("changed.go") cue := "⚠ DEBUG target " + client.SessionHandle(m.deps.DebugTarget) - budget := m.width - 2 - lipgloss.Width(cue) - 5 - lipgloss.Width(autoBadgeText) - 2 - lipgloss.Width("✎ 1 file") - headerGapPad + budget := m.width - 2 - lipgloss.Width(cue) - 5 - lipgloss.Width(client.ProjectUntrusted) - 2 - lipgloss.Width("✎ 1 file") - headerGapPad if budget <= 0 { t.Fatalf("no command header budget: %d", budget) } @@ -214,7 +214,7 @@ func TestCanonicalStatus_Scenario2_DebugCommandSourceReceivesReservedWidth(t *te m = updated.(Model) header := stripANSIstr(m.renderHeader()) first := strings.Split(header, "\n")[0] - if i, j := strings.Index(first, cue), strings.Index(first, identity); i < 0 || j <= i || !strings.Contains(first, autoBadgeText) || !strings.Contains(first, "✎ 1 file") || strings.Contains(header, "wrong-budget") || lipgloss.Width(first) > m.width { + if i, j := strings.Index(first, cue), strings.Index(first, identity); i < 0 || j <= i || !strings.Contains(first, client.ProjectUntrusted) || !strings.Contains(first, "✎ 1 file") || strings.Contains(header, "wrong-budget") || lipgloss.Width(first) > m.width { t.Fatalf("command source width %d displaced debug warning or indicator: %q (surface %#v)", budget, header, m.generatedStatusLine.Header) } if !m.generatedStatusLine.Header.Present || !statusSurfaceFits(m.generatedStatusLine.Header, budget) || !strings.Contains(header, "PRIVACY:") { @@ -236,10 +236,10 @@ func TestCanonicalStatus_Scenario2_DebugReservationReachesSource(t *testing.T) { if first.Terminal.HeaderAvailCols != m.statusLineGeometry().headerAvailable || first.Terminal.HeaderAvailCols > 120-2-warningWidth { t.Fatalf("warning not reserved: %#v", first.Terminal) } - m = applyAll(m, client.SessionReadyMsg{SessionID: m.sessionID, Capabilities: client.Capabilities{Posture: postureAuto}}) + m = applyAll(m, client.SessionReadyMsg{SessionID: m.sessionID, Capabilities: client.Capabilities{Posture: postureAuto, ProjectTrust: client.ProjectTrusted}}) second, _ := source.lastInput() if second.Terminal.HeaderAvailCols >= first.Terminal.HeaderAvailCols { - t.Fatalf("posture did not reserve: %d -> %d", first.Terminal.HeaderAvailCols, second.Terminal.HeaderAvailCols) + t.Fatalf("trust badge did not reserve: %d -> %d", first.Terminal.HeaderAvailCols, second.Terminal.HeaderAvailCols) } m = applyAll(m, client.ToolCallMsg{ID: "write-1", Name: "Write", Args: `{"path":"changed.go","content":"x"}`}) withNavigation, _ := source.lastInput() diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go index aad7fbb5b2..4c39a33b1c 100644 --- a/cmd/mecatui/ui/mode_cycle.go +++ b/cmd/mecatui/ui/mode_cycle.go @@ -92,7 +92,11 @@ func nextModeToken(cur string) string { // posture cannot, because the posture is fixed when the server starts, so the // cycle stops on it and says what to configure and restart. func (m Model) cycleMode() (tea.Model, tea.Cmd) { - next := permissionModeEntry(nextModeToken(m.currentModeToken())) + cur := m.currentModeToken() + if m.modeRefused != "" { + cur, m.modeRefused = m.modeRefused, "" + } + next := permissionModeEntry(nextModeToken(cur)) if postureRank(next.Posture) > postureRank(m.caps.Posture) { m.modeCursor = modeCursor{token: next.Name, session: m.desiredMode()} m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeBlockedStatus()) diff --git a/cmd/mecatui/ui/mode_test.go b/cmd/mecatui/ui/mode_test.go index dd53bac8f6..4bc7ff7448 100644 --- a/cmd/mecatui/ui/mode_test.go +++ b/cmd/mecatui/ui/mode_test.go @@ -124,6 +124,87 @@ func TestModeSwitchFailureDefersToNextPrompt(t *testing.T) { } } +// TestModeRefusedAtIdleClearsPending pins that a SetMode error with no turn in +// flight is the server's final refusal: the header must not stay "pending" +// and the status names the server's reason. +func TestModeRefusedAtIdleClearsPending(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default", setModeErr: errors.New("set mode: mode \"plan\" exceeds the server ceiling")} + m := modeTestModel(t, conv) + + mm, cmd := m.Update(modeKey()) + m = mm.(Model) + if cmd == nil { + t.Fatal("shift+tab should issue SetMode command") + } + m = applyAll(m, cmd()) + + if m.activeMode != "default" || m.pendingMode != "" { + t.Fatalf("active/pending mode = %q/%q, want default/empty", m.activeMode, m.pendingMode) + } + status := stripANSIstr(m.statusMsg) + if !strings.Contains(status, "mode plan refused") || !strings.Contains(status, "exceeds the server ceiling") { + t.Fatalf("status = %q, want refusal naming the server reason", status) + } + if mode := m.statusLineSnapshot().Session.Mode; mode != "default" { + t.Fatalf("status snapshot mode = %q, want default", mode) + } + if m.retryPendingModeCmd() != nil { + t.Fatal("a refused mode must not be retried at the next turn boundary") + } +} + +// TestRefusedModeDoesNotTrapCycle pins that after the server refuses a mode +// the next ModeSwitch continues past it instead of re-requesting it forever: +// on a yolo server an auto refusal still lets the cycle reach yolo. +func TestRefusedModeDoesNotTrapCycle(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "accept-edits"} + m := newTestModelFromDeps(Deps{Session: conv, Conv: conv, Theme: theme.New("aztec", theme.AztecPalette()), Mode: "accept-edits", Ctx: context.Background(), Embedded: true}) + m = applyAll(m, tea.WindowSizeMsg{Width: 120, Height: 30}, client.SessionReadyMsg{SessionID: "sess-test-0001", Mode: "accept-edits"}) + m.caps.Posture = postureYolo + + press := func() { + t.Helper() + mm, cmd := m.Update(modeKey()) + m = mm.(Model) + if cmd != nil { + m = applyAll(m, cmd()) + } + } + conv.setModeErr = errors.New(`mode "auto" requires an enforcing guardrails checker`) + press() + if m.activeMode != "accept-edits" || !strings.Contains(stripANSIstr(m.statusMsg), "mode auto refused") { + t.Fatalf("after auto refusal: active=%q status=%q", m.activeMode, stripANSIstr(m.statusMsg)) + } + conv.setModeErr = nil + press() + if got := conv.setModes(); len(got) != 2 || got[1] != "yolo" { + t.Fatalf("SetMode calls = %v, want [auto yolo]", got) + } + if m.activeMode != "yolo" || m.headerMode() != "yolo" { + t.Fatalf("active/header = %q/%q, want yolo", m.activeMode, m.headerMode()) + } +} + +// TestModeMismatchAdoptsServerMode pins that a SetMode reply naming a +// different mode than requested is adopted, not swallowed into a permanent +// "pending" header. +func TestModeMismatchAdoptsServerMode(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := modeTestModel(t, conv) + m.pendingMode = "auto" + + m = applyAll(m, client.ModeChangedMsg{SessionID: "sess-test-0001", Requested: "auto", Mode: "default"}) + if m.activeMode != "default" || m.pendingMode != "" { + t.Fatalf("active/pending mode = %q/%q, want default/empty", m.activeMode, m.pendingMode) + } + if status := stripANSIstr(m.statusMsg); !strings.Contains(status, "mode auto not applied") || !strings.Contains(status, "kept default") { + t.Fatalf("status = %q, want mismatch notice", status) + } + if strings.Contains(m.headerMode(), "pending") { + t.Fatalf("header mode = %q, must not stay pending", m.headerMode()) + } +} + func TestStaleModeResponseDoesNotClobberNewerRequest(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := modeTestModel(t, conv) diff --git a/cmd/mecatui/ui/model.go b/cmd/mecatui/ui/model.go index dc8200eaba..9eccb8ef6a 100644 --- a/cmd/mecatui/ui/model.go +++ b/cmd/mecatui/ui/model.go @@ -825,6 +825,9 @@ type Model struct { // modeCursor is where the ModeSwitch cycle over every permission mode last // landed, including a mode that needs a restart and so changed nothing. modeCursor modeCursor + // modeRefused is the mode the server just refused. The next ModeSwitch + // continues the cycle after it, so a refused mode does not trap the cycle. + modeRefused string // fullColor is true on a truecolor terminal, derived from the tea.ColorProfileMsg // (msg.Profile == colorprofile.TrueColor) in the reducer. It gates the welcome diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index bca916b538..89f09721aa 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -297,36 +297,25 @@ func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { } } -// TestHeaderShowsPostureWhenAboveStrict pins that the header shows the -// session mode, and a posture badge for every tier above strict (trusted now -// included), sourced from the server-reported caps.Posture. -func TestHeaderShowsPostureWhenAboveStrict(t *testing.T) { - cases := []struct { - posture string - badge string // "" = no badge - }{ - {postureStrict, ""}, - {postureTrusted, trustedBadgeText}, - {postureAuto, "⚠ auto"}, - {postureYolo, "YOLO"}, - } - for _, tc := range cases { - t.Run(tc.posture, func(t *testing.T) { +// TestHeaderShowsModeNotPosture pins that the header shows the session mode and +// no posture badge at any tier: the posture is not a header axis, only the +// mode the cycle lands on and (separately) project trust. +func TestHeaderShowsModeNotPosture(t *testing.T) { + for _, posture := range []string{postureStrict, postureTrusted, postureAuto, postureYolo} { + t.Run(posture, func(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} - m := permissionModeTestModel(t, conv, tc.posture, true) + m := permissionModeTestModel(t, conv, posture, true) header := stripANSIstr(m.renderHeader()) if got := statusMode(m); got != "default" { t.Errorf("status mode = %q, want default", got) } - badge, _ := m.postureBadgeRender() - if tc.badge == "" { - if badge != "" || strings.Contains(header, "posture") || strings.Contains(header, "strict") { - t.Errorf("strict must render no posture badge, got %q", header) - } - return + if badge, _ := m.postureBadgeRender(); badge != "" { + t.Errorf("posture %s rendered a badge without reported trust: %q", posture, badge) } - if badge == "" || !strings.Contains(header, tc.badge) { - t.Errorf("posture %s: header missing badge %q: %q", tc.posture, tc.badge, header) + for _, gone := range []string{"YOLO", "⚠ auto", "trusted"} { + if strings.Contains(header, gone) { + t.Errorf("posture %s: header carries posture badge %q: %q", posture, gone, header) + } } }) } @@ -334,7 +323,7 @@ func TestHeaderShowsPostureWhenAboveStrict(t *testing.T) { // TestHeaderKeepsPostureAcrossModeCycle pins that under auto, cycling through // yolo (blocked: above the auto ceiling), then through lower modes keeps the -// auto badge on every frame, including the pending frames before the server +// trust badge on every frame, including the pending frames before the server // confirms each switch. // // A session on an auto-posture server starts in "auto" mode. The cycle order @@ -354,14 +343,14 @@ func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { }) m = applyAll(m, tea.WindowSizeMsg{Width: 140, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-auto-cycle", Mode: "auto", Capabilities: client.Capabilities{Posture: postureAuto}}, + client.SessionReadyMsg{SessionID: "sess-auto-cycle", Mode: "auto", Capabilities: client.Capabilities{Posture: postureAuto, ProjectTrust: client.ProjectTrusted}}, ) assertAuto := func(step, wantMode string) { t.Helper() header := stripANSIstr(m.renderHeader()) - if !strings.Contains(header, autoBadgeText) { - t.Fatalf("%s: header lost the auto posture badge: %q", step, header) + if !strings.Contains(header, client.ProjectTrusted) { + t.Fatalf("%s: header lost the trust badge: %q", step, header) } if got := statusMode(m); got != wantMode { t.Fatalf("%s: status mode = %q, want %q", step, got, wantMode) diff --git a/cmd/mecatui/ui/posture_badge_test.go b/cmd/mecatui/ui/posture_badge_test.go index f3ee766649..14a160eda1 100644 --- a/cmd/mecatui/ui/posture_badge_test.go +++ b/cmd/mecatui/ui/posture_badge_test.go @@ -11,241 +11,84 @@ import ( "github.com/stacklok/mecatl/cmd/mecatui/theme" ) -// TestPostureBadgeShownForAutoYolo asserts the header renders the auto/yolo chrome -// badge when the server reports an allow-all posture, the quieter trusted badge for -// trusted, and NO badge for strict (and an empty/older-server posture) — -// the goldens-stability guarantee. Under -// MECATUI_NO_EMOJI the yolo badge is the clean " YOLO " pill with NO lightning bolt and -// NO VS16; auto is "⚠ auto". The badge is sourced from caps.Posture (SessionReadyMsg), -// NOT the per-session mode segment. -func TestPostureBadgeShownForAutoYolo(t *testing.T) { - cases := []struct { - posture string - wantBadge string // "" = no badge - }{ - {"", ""}, - {"strict", ""}, - {"trusted", "trusted"}, - {"auto", "⚠ auto"}, - {"yolo", "YOLO"}, - } - for _, tc := range cases { - m, _, _ := newTestModel(t, theme.New("aztec", theme.AztecPalette())) - m = applyAll(m, tea.WindowSizeMsg{Width: 100, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: tc.posture}}) - - raw := m.renderHeader() - header := stripANSIstr(raw) - if tc.wantBadge == "" { - // No badge for strict/unset: no posture glyph or word may appear. - if strings.Contains(header, "⚠") || strings.Contains(header, "⚡") || strings.Contains(header, "YOLO") || strings.Contains(header, "posture") { - t.Errorf("posture %q: header must show NO badge, got %q", tc.posture, header) - } - continue - } - if !strings.Contains(header, tc.wantBadge) { - t.Errorf("posture %q: header missing %q badge, got %q", tc.posture, tc.wantBadge, header) - } - if tc.posture == "yolo" { - // No-emoji yolo: a CLEAN pill — no bolt, no VS16. - if strings.Contains(header, "⚡") { - t.Errorf("no-emoji yolo badge must carry NO lightning bolt, got %q", header) - } - if strings.Contains(raw, vs16) { - t.Errorf("no-emoji yolo badge must carry NO VS16, got %q", header) - } - } - } -} - -// TestPostureBadgeCarriesWarningStyle asserts the badge is rendered in the CORRECT -// per-tier style — auto in the THEME's "warning" style (inline coloured text), and the -// yolo pill in the "dangerPill" style (the filled alarm-red chip) — and NEVER the muted -// style the benign scroll/changed-files cues use. The one persistent in-session danger -// cue must READ as danger. It checks the RAW (un-stripped) header for the exact styled -// substring (so a regression to the empty-fallback or muted style trips it) and confirms -// the not-muted guard. -func TestPostureBadgeCarriesWarningStyle(t *testing.T) { +// TestTrustBadgeShowsProjectTrust asserts the header's right-aligned badge shows +// the server-reported project trust, independent of posture and permission mode: +// "trusted" in the warning style, "untrusted" muted, and no badge from an older +// server that does not report trust. No posture tier renders a badge of its own. +func TestTrustBadgeShowsProjectTrust(t *testing.T) { th := theme.New("aztec", theme.AztecPalette()) cases := []struct { + trust string posture string - text string // the styled segment's content - slot string // the style slot it must be rendered in + slot string // "" = no badge }{ - {"auto", autoBadgeText, "warning"}, - {"yolo", yoloPillText, "dangerPill"}, + {"", postureYolo, ""}, + {client.ProjectUntrusted, postureStrict, "muted"}, + {client.ProjectUntrusted, postureYolo, "muted"}, + {client.ProjectTrusted, postureStrict, "warning"}, + {client.ProjectTrusted, postureAuto, "warning"}, } for _, tc := range cases { m, _, _ := newTestModel(t, th) m = applyAll(m, tea.WindowSizeMsg{Width: 100, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: tc.posture}}) - + client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: tc.posture, ProjectTrust: tc.trust}}) raw := m.renderHeader() - wantStyled := th.Style(tc.slot).Render(tc.text) - // The styled segment MUST be non-empty (guards against an empty-fallback slot). - if stripANSIstr(wantStyled) == "" { - t.Fatalf("posture %q: the %q style render is empty — the slot is missing", tc.posture, tc.slot) + header := stripANSIstr(raw) + for _, gone := range []string{"YOLO", "⚠ auto", "⚡"} { + if strings.Contains(header, gone) { + t.Errorf("trust %q posture %q: header must not carry a posture badge %q: %q", tc.trust, tc.posture, gone, header) + } } - if !strings.Contains(raw, wantStyled) { - t.Errorf("posture %q: header must render the badge in the %q style; want substring %q in %q", tc.posture, tc.slot, wantStyled, raw) + if tc.slot == "" { + if strings.Contains(header, "trusted") { + t.Errorf("unreported trust must render no badge: %q", header) + } + continue } - // Guard against a regression to the muted style (the benign-cue weight). - mutedBadge := th.Style("muted").Render(tc.text) - if mutedBadge != wantStyled && strings.Contains(raw, mutedBadge) { - t.Errorf("posture %q: badge must NOT be muted-styled (it is a danger cue); found muted render %q", tc.posture, mutedBadge) + if want := th.Style(tc.slot).Render(tc.trust); !strings.Contains(raw, want) { + t.Errorf("trust %q: header must render %q in the %q style; got %q", tc.trust, tc.trust, tc.slot, raw) } } } -// TestPostureBadgeYoloIsRedPill asserts the yolo pill is the FILLED, FIXED-COLOUR alarm -// chip — distinct from the auto badge's inline warning text and from the theme's Error -// colour — the loudest posture must read loudest and identically across themes. It pins -// the dangerPill's theme-independent alarm-red background + near-white foreground. -func TestPostureBadgeYoloIsRedPill(t *testing.T) { - th := theme.New("aztec", theme.AztecPalette()) - m, _, _ := newTestModel(t, th) - m = applyAll(m, tea.WindowSizeMsg{Width: 100, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: "yolo"}}) - raw := m.renderHeader() - - pill := th.Style("dangerPill").Render(yoloPillText) - warn := th.Style("warning").Render(yoloPillText) - if pill == warn { - t.Fatal("dangerPill and warning must render differently (the pill is filled, the warning is inline)") - } - if !strings.Contains(raw, pill) { - t.Errorf("yolo header must render the danger PILL; want %q in %q", pill, raw) - } - // The pill carries the FIXED alarm-red background + near-white foreground RGB SGRs, - // NOT the theme Error / Bg pair — danger is danger across every theme. - for _, want := range []string{"\x1b[", "224;49;49", "245;245;245"} { // #E03131 / #F5F5F5 as RGB - if !strings.Contains(pill, want) { - t.Errorf("dangerPill render missing fixed alarm colour %q: %q", want, pill) - } - } -} - -// TestPostureBadgeIsNotModeSegment guards that the badge is DISTINCT from the per-session -// `mode` segment: with posture auto and a default permission mode, the header carries -// the auto badge but no "mode auto" text (the mode segment renders the PermissionMode, -// here unset, never the posture). -func TestPostureBadgeIsNotModeSegment(t *testing.T) { +// TestTrustBadgeIsNotModeSegment guards that the badge is DISTINCT from the +// per-session mode segment: on an auto server the header carries the trust badge +// and the mode segment carries the session mode, never the posture. +func TestTrustBadgeIsNotModeSegment(t *testing.T) { m, _, _ := newTestModel(t, theme.New("aztec", theme.AztecPalette())) m = applyAll(m, tea.WindowSizeMsg{Width: 120, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: "auto"}}) + client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: postureAuto, ProjectTrust: client.ProjectTrusted}}) header := stripANSIstr(m.renderHeader()) - if !strings.Contains(header, "⚠ auto") { - t.Fatalf("expected the auto posture badge; got %q", header) + if !strings.Contains(header, "trusted") { + t.Fatalf("expected the trust badge; got %q", header) } if strings.Contains(header, "mode auto") { t.Fatalf("posture must not leak into the mode segment; got %q", header) } } -// vs16 is the U+FE0F variation selector — the byte whose PRESENCE distinguishes the -// emoji-presentation yolo badge ("⚡️ YOLO") from the width-stable text one ("⚡ YOLO"). -const vs16 = "️" - -// TestPostureBadgeEmojiVariant pins the yolo badge variants: an emoji-capable -// model renders a PLAIN ⚡️ bolt (with VS16) OUTSIDE the danger pill; an incapable -// model renders just the clean " YOLO " pill. The capability is injected before -// New because detection is evaluated once at construction. -func TestPostureBadgeEmojiVariant(t *testing.T) { - cases := []struct { - name string - emojiOK bool - wantBolt bool - }{ - {"emoji forced", true, true}, - {"emoji off", false, false}, - } - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - th := theme.New("aztec", theme.AztecPalette()) - m, _, _ := newTestModel(t, th, func(deps *Deps) { - deps.emojiCapable = func() bool { return tc.emojiOK } - }) - m = applyAll(m, tea.WindowSizeMsg{Width: 100, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: "yolo"}}) - - raw := m.renderHeader() - header := stripANSIstr(raw) - - // The clean pill is present (dangerPill-styled " YOLO ") in BOTH variants. - pill := th.Style("dangerPill").Render(yoloPillText) - if !strings.Contains(raw, pill) { - t.Errorf("yolo header must render the clean danger pill %q in %q", pill, raw) - } - // The pill itself must NOT contain the bolt — the emoji is decoration OUTSIDE. - if strings.Contains(pill, "⚡") { - t.Fatal("the dangerPill render must not contain the lightning bolt") - } - if !strings.Contains(header, "YOLO") { - t.Errorf("yolo header missing YOLO, got %q", header) - } - - gotBolt := strings.Contains(raw, "⚡") - gotVS16 := strings.Contains(raw, vs16) - if gotBolt != tc.wantBolt || gotVS16 != tc.wantBolt { - t.Errorf("%s: bolt present=%v VS16 present=%v, want both %v", tc.name, gotBolt, gotVS16, tc.wantBolt) - } - if tc.wantBolt { - // The PLAIN bolt prefix appears IMMEDIATELY BEFORE the styled pill — i.e. - // the raw header contains "" with the bolt NOT - // inside the pill's SGR run. - if !strings.Contains(raw, yoloBoltPrefix+pill) { - t.Errorf("emoji yolo: plain bolt prefix must immediately precede the pill; want %q before pill in %q", yoloBoltPrefix, raw) - } - } - }) - } -} - -// TestYoloBadgeWithTailFitsOneRow is the fitHeader pill-width-math guard (the one -// genuinely tricky arithmetic): with posture=yolo AND a non-empty right-aligned tail -// (a changed-files cue), at a band of narrow-but-fitting widths, appending the YOLO -// danger pill beside the tail must NOT add a header row beyond what the identity line -// alone already produces, and must never exceed the terminal width. The baseline is the -// SAME model at strict posture (no badge): fitHeader only appends the indicator when it -// FITS within the gap, so a correctly-compensated pill leaves the row count identical to -// the no-badge baseline (it never forces a wrap) and the width within w. This isolates -// the pill arithmetic from the pre-existing identity-line wrap (which is width-driven and -// independent of the badge). Both glyph variants are covered because ⚡️ (width-2) and ⚡ -// (text, width-1) make the pill — and thus the +2-padded gap math — different widths. -func TestYoloBadgeWithTailFitsOneRow(t *testing.T) { - cases := []struct { - name string - emojiOK bool - }{ - {"text glyph", false}, - {"emoji glyph", true}, - } - mkHeader := func(t *testing.T, th theme.Theme, posture string, w int, emojiOK bool) string { - m, _, _ := newTestModel(t, th, func(deps *Deps) { - deps.emojiCapable = func() bool { return emojiOK } - }) +// TestTrustBadgeWithTailFitsOneRow is the fitHeader width-math guard: with the +// widest badge ("untrusted") AND a right-aligned changed-files tail, the header +// must not add a row beyond the no-badge baseline nor exceed the terminal width. +func TestTrustBadgeWithTailFitsOneRow(t *testing.T) { + th := theme.New("aztec", theme.AztecPalette()) + mkHeader := func(trust string, w int) string { + m, _, _ := newTestModel(t, th) m = applyAll(m, tea.WindowSizeMsg{Width: w, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: posture}}) - // A changed-files cue gives a non-empty right-aligned tail beside the badge. + client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{ProjectTrust: trust}}) m.conv.recordFileChange("a.go") m.conv.recordFileChange("b.go") return m.renderHeader() } - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - th := theme.New("aztec", theme.AztecPalette()) - - for w := 60; w <= 120; w += 5 { - baseRows := lipgloss.Height(mkHeader(t, th, "strict", w, tc.emojiOK)) // no badge - header := mkHeader(t, th, "yolo", w, tc.emojiOK) // pill + tail - if rows := lipgloss.Height(header); rows != baseRows { - t.Errorf("%s width %d: yolo header is %d rows, want %d (the no-badge baseline) — the pill must not force an extra wrap", tc.name, w, rows, baseRows) - } - if gotW := lipgloss.Width(header); gotW > w { - t.Errorf("%s width %d: yolo header rendered %d cols, want ≤ %d (pill+tail must not overflow)", tc.name, w, gotW, w) - } - } - }) + for w := 60; w <= 120; w += 5 { + baseRows := lipgloss.Height(mkHeader("", w)) + header := mkHeader(client.ProjectUntrusted, w) + if rows := lipgloss.Height(header); rows != baseRows { + t.Errorf("width %d: header is %d rows, want %d (the no-badge baseline)", w, rows, baseRows) + } + if gotW := lipgloss.Width(header); gotW > w { + t.Errorf("width %d: header rendered %d cols, want ≤ %d", w, gotW, w) + } } } @@ -265,7 +108,7 @@ func TestPostureSummary(t *testing.T) { {"yolo", []string{"posture yolo", "ceiling all modes including yolo", "child $()/heredoc auto-run when in yolo mode (injection-defense off) on", "project-trust on"}}, } for _, tc := range cases { - got := postureSummary(tc.posture) + got := postureSummary(tc.posture, "") for _, sub := range tc.want { if !strings.Contains(got, sub) { t.Errorf("postureSummary(%q) missing %q; got %q", tc.posture, sub, got) diff --git a/cmd/mecatui/ui/statusline.go b/cmd/mecatui/ui/statusline.go index 63f47855fe..08d180593b 100644 --- a/cmd/mecatui/ui/statusline.go +++ b/cmd/mecatui/ui/statusline.go @@ -40,6 +40,13 @@ func renderStatusSpans(th theme.Theme, spans []customization.Span) string { continue } style := lipgloss.NewStyle() + if span.Token == customization.TokenDanger { + // The yolo alarm pill: the dangerPill fill without its padding, so the + // span's own text (which carries the pill's spaces) is its exact width + // and the plain-text fit math stays correct. + b.WriteString(th.Style("dangerPill").UnsetPadding().Render(text)) + continue + } if span.Href != "" { b.WriteString(style.Foreground(lipgloss.Color(th.Palette.MdLink)).Underline(true).Hyperlink(span.Href).Render(text)) continue diff --git a/cmd/mecatui/ui/statusline_source.go b/cmd/mecatui/ui/statusline_source.go index 290cc81af1..b90352f84f 100644 --- a/cmd/mecatui/ui/statusline_source.go +++ b/cmd/mecatui/ui/statusline_source.go @@ -214,7 +214,7 @@ func (m Model) statusLineInput(now time.Time) customization.Input { MainAgent: customization.MainAgent{State: state, Activity: activity, Approval: approval}, Delegation: m.statusDelegation(), Clock: customization.Clock{Now: now}, - Terminal: customization.Terminal{Rows: m.height, Cols: m.widthOr(), HeaderAvailCols: geometry.headerAvailable, FooterAvailCols: geometry.footerAvailable}, + Terminal: customization.Terminal{Rows: m.height, Cols: m.widthOr(), HeaderAvailCols: geometry.headerAvailable, FooterAvailCols: geometry.footerAvailable, Emoji: m.emojiOK}, } } diff --git a/cmd/mecatui/ui/statusline_test.go b/cmd/mecatui/ui/statusline_test.go index e5c2b6a30f..b2ece490d8 100644 --- a/cmd/mecatui/ui/statusline_test.go +++ b/cmd/mecatui/ui/statusline_test.go @@ -9,6 +9,7 @@ import ( tea "charm.land/bubbletea/v2" "charm.land/lipgloss/v2" + "github.com/stacklok/mecatl/cmd/mecatui/client" customization "github.com/stacklok/mecatl/cmd/mecatui/customization" "github.com/stacklok/mecatl/cmd/mecatui/theme" ) @@ -42,6 +43,61 @@ func TestStatusLine_Scenario2_DefaultTemplatesPreserveChrome(t *testing.T) { } } } + +// TestStatusLine_YoloModeRendersAlarmPill pins that the shipped header marks +// the yolo mode with the filled alarm pill (the theme-independent dangerPill +// colours around "YOLO"), and every other mode — including a pending yolo — as +// plain "mode " text with no pill. On an emoji-capable terminal a ⚡️ +// bolt (VS16 intact) precedes the pill, outside its fill; otherwise no bolt. +func TestStatusLine_YoloModeRendersAlarmPill(t *testing.T) { + th := theme.New("aztec", theme.AztecPalette()) + renderWith := func(mode string, emoji bool) string { + t.Helper() + s := customization.NewDefaultSource(0) + t.Cleanup(func() { _ = s.Close(context.Background()) }) + m, _, _ := newTestModel(t, th, func(deps *Deps) { + deps.emojiCapable = func() bool { return emoji } + }) + m.deps.StatusSource = s + m.sessionID = "session-yolo-pill" + m.phase = phaseIdle + m.activeMode = mode + m.caps.Posture = postureYolo + updated, _ := m.Update(tea.WindowSizeMsg{Width: 100, Height: 24}) + m = updated.(Model) + updated, _ = m.update(waitStatusMessage(t, m.statusLineWaitCmd())) + return updated.(Model).renderHeader() + } + render := func(mode string) string { return renderWith(mode, false) } + pill := th.Style("dangerPill").UnsetPadding().Render(" YOLO ") + if want := th.Style("dangerPill").Render(" YOLO "); stripANSIstr(pill) != stripANSIstr(want) || lipgloss.Width(pill) != lipgloss.Width(want) { + t.Fatalf("mode pill %q must match the posture pill %q cell for cell", pill, want) + } + for _, sgr := range []string{"224;49;49", "245;245;245"} { // #E03131 / #F5F5F5 + if !strings.Contains(pill, sgr) { + t.Fatalf("mode pill missing the fixed alarm colour %q: %q", sgr, pill) + } + } + raw := render("yolo") + if !strings.Contains(raw, pill) || !strings.Contains(stripANSIstr(raw), "mode YOLO") || strings.Contains(raw, "⚡") { + t.Fatalf("no-emoji yolo header must carry the bare alarm pill %q: %q", pill, raw) + } + emoji := renderWith("yolo", true) + bolt := strings.Index(emoji, "⚡️ ") + if bolt < 0 || !strings.Contains(emoji, pill) || bolt > strings.Index(emoji, pill) || strings.Contains(pill, "⚡") { + t.Fatalf("emoji yolo header must put the ⚡️ bolt (with VS16) before the pill, outside its fill: %q", emoji) + } + if !strings.Contains(stripANSIstr(emoji), "mode ⚡️ YOLO") { + t.Fatalf("emoji yolo header text = %q", stripANSIstr(emoji)) + } + for _, mode := range []string{"auto", "default"} { + raw := render(mode) + if strings.Contains(raw, "224;49;49") || !strings.Contains(stripANSIstr(raw), "mode "+mode) { + t.Fatalf("%s header must be plain mode text without the pill: %q", mode, raw) + } + } +} + func TestStatusLine_StaleGeneratedSurfaceNeverWraps(t *testing.T) { m, _, _ := newTestModel(t, theme.New("aztec", theme.AztecPalette())) m.deps.StatusSource = &statusSourceFake{changed: make(chan struct{})} @@ -95,10 +151,10 @@ func TestStatusLine_Scenario2_HeaderSystemIndicatorsSurviveOverride(t *testing.T m.width = 100 m.generatedStatusLine.Header = customization.Render(`
CUSTOM
`, nil).Header m.deps.StatusSource = &statusSourceFake{changed: make(chan struct{})} - m.caps.Posture = postureAuto + m.caps.ProjectTrust = client.ProjectUntrusted m.conv.recordFileChange("changed.go") header := stripANSIstr(m.renderHeader()) - for _, want := range []string{"CUSTOM", autoBadgeText, "✎ 1 file"} { + for _, want := range []string{"CUSTOM", client.ProjectUntrusted, "✎ 1 file"} { if !strings.Contains(header, want) { t.Errorf("missing %q in %q", want, header) } diff --git a/cmd/mecatui/ui/update.go b/cmd/mecatui/ui/update.go index 91f15fd0df..68857b86eb 100644 --- a/cmd/mecatui/ui/update.go +++ b/cmd/mecatui/ui/update.go @@ -1122,7 +1122,7 @@ func (m Model) updateLifecycle(msg tea.Msg) (tea.Model, tea.Cmd, bool) { if msg.Err == nil { checker = guardrailPostureSummary(msg.Coverage) } - m.statusMsg = m.deps.Theme.Style("muted").Render(postureSummary(m.caps.Posture) + "; " + checker) + m.statusMsg = m.deps.Theme.Style("muted").Render(postureSummary(m.caps.Posture, m.caps.ProjectTrust) + "; " + checker) } else if msg.Err != nil { m.conv.addNotice("Guardrails status unavailable; checker state is unknown, not off or healthy.") } else { @@ -2701,16 +2701,32 @@ func (m Model) onModeChanged(msg client.ModeChangedMsg) tea.Model { return m } if msg.Err != nil { + if m.phase == phaseIdle { + // No turn is in flight, so this is the server's final refusal (ceiling, + // missing checker), not the mid-turn deferral: retrying cannot succeed. + m.pendingMode = "" + m.modeCursor = modeCursor{} + m.modeRefused = requested + m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + requested + " refused: " + client.ModeErrorText(msg.Err)) + return m + } m.pendingMode = requested m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + m.pendingMode + " will apply on the next prompt") return m } mode := client.ModeString(client.ModeFromString(msg.Mode)) if mode != requested { + // The server applied a different mode than requested (e.g. an older server + // that does not know it). Adopt what it reports instead of staying pending. + m.activeMode = mode + m.pendingMode = "" + m.modeCursor = modeCursor{} + m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + requested + " not applied: the server kept " + mode) return m } m.activeMode = mode m.pendingMode = "" + m.modeRefused = "" label := mode if m.modeCursor.session == mode { label = m.modeLabel(permissionModeEntry(m.modeCursor.token)) diff --git a/cmd/mecatui/ui/view.go b/cmd/mecatui/ui/view.go index 76519e6495..539af1cdfb 100644 --- a/cmd/mecatui/ui/view.go +++ b/cmd/mecatui/ui/view.go @@ -182,70 +182,20 @@ const ( postureYolo = "yolo" ) -// autoBadgeText is the auto-posture badge: amber inline WARNING text (no pill). -const autoBadgeText = "⚠ auto" - -// trustedBadgeText is the trusted-posture badge: inline warning-styled text naming -// the posture, with no glyph so it reads quieter than the allow-all tiers. -const trustedBadgeText = "trusted" - -// yoloPillText is the YOLO pill's CONTENT — just the word, padded by a space each side -// so the filled dangerPill chip has visual breathing room around "YOLO". The pill never -// contains the lightning bolt: the emoji (when shown) rides OUTSIDE the pill as plain -// decoration (see postureBadgeRender) — VTE renders ⚡️ in its own multicolour glyph and -// IGNORES a foreground, which clashed inside the dark-on-red pill. -const yoloPillText = " YOLO " - -// yoloBoltPrefix is the PLAIN (unstyled) emoji bolt shown immediately BEFORE the YOLO -// pill on an emoji-capable terminal — ⚡ + U+FE0F (VS16) for the width-2 emoji -// presentation, plus a trailing space. It is decoration OUTSIDE the pill, so the -// terminal shows the bolt's natural colour and the pill stays a clean dark-on-red chip. -// The VS16 MUST survive to the screen — the header path renders via lipgloss styles only -// and never routes the badge through normalizeEmojiWidth/wrapStyled (which strip VS16). -const yoloBoltPrefix = "⚡️ " - -// postureBadgeRender builds the right-aligned operator-posture chrome badge — the STYLED -// string ready to drop into the header AND its visible (plain) cell width for the -// fit/shed math. It surfaces the SERVER-WIDE posture (m.caps.Posture) whenever it is -// above strict — strict/unknown render NO badge, so the steady-state frame and the -// goldens stay byte-identical. It is DISTINCT from the per-session `mode` segment, and a -// session-mode cycle never changes it. -// -// Tiers: -// - trusted → warning-styled inline text "trusted". -// - auto → amber inline WARNING text "⚠ auto". -// - yolo → a clean filled DANGER PILL (dangerPill style) of " YOLO ", optionally -// PRECEDED by a PLAIN ⚡️ emoji bolt when m.emojiOK (seeded once at New). The bolt is -// pure decoration OUTSIDE the pill; the pill is always a clean dark-on-red chip. -// -// The plain width is computed to match the ACTUAL rendered glyphs: the dangerPill's -// Padding(0,1) adds 2 cells lipgloss.Width(yoloPillText) does count (the text already -// carries its spaces), so the pill's visible width is lipgloss.Width(yoloPillText)+2; the -// optional bolt prefix adds lipgloss.Width(yoloBoltPrefix) (⚡️ width-2 + space). +// postureBadgeRender builds the right-aligned project-trust chrome badge — the +// STYLED string ready to drop into the header AND its visible (plain) cell width +// for the fit/shed math. It shows the server-reported project trust +// (m.caps.ProjectTrust), an axis independent of the permission mode: "trusted" +// in the warning style (the project's rules and instructions are honoured), or +// "untrusted" muted. The permission mode, including auto and yolo, is shown only +// by the cycling mode segment. An older server reports no trust, so no badge. func (m Model) postureBadgeRender() (styled string, plainWidth int) { - switch m.caps.Posture { - case postureAuto: - return m.deps.Theme.Style("warning").Render(autoBadgeText), lipgloss.Width(autoBadgeText) - case postureYolo: - pill := m.deps.Theme.Style("dangerPill").Render(yoloPillText) - // The pill's visible width = its text cells + the 2 padding cells the style adds. - w := lipgloss.Width(yoloPillText) + 2 - if m.emojiOK { - // PLAIN bolt prefix (no style) so VTE shows its natural emoji colour. - return yoloBoltPrefix + pill, lipgloss.Width(yoloBoltPrefix) + w - } - return pill, w - case postureTrusted: - // Above strict: the project's rules and instructions are - // honoured process-wide, so the header must not read as a plain default - // session. Warning-styled text, no glyph, quieter than auto's. - return m.deps.Theme.Style("warning").Render(trustedBadgeText), lipgloss.Width(trustedBadgeText) - case postureStrict: - // Strict carries no badge — the steady-state frame stays byte-identical (the - // goldens are captured at strict). - return "", 0 + switch t := m.caps.ProjectTrust; t { + case client.ProjectTrusted: + return m.deps.Theme.Style("warning").Render(t), lipgloss.Width(t) + case client.ProjectUntrusted: + return m.deps.Theme.Style("muted").Render(t), lipgloss.Width(t) default: - // Unknown / older-server posture: no badge. return "", 0 } } diff --git a/contracts/gen/go/mecatl/v1/harness.pb.go b/contracts/gen/go/mecatl/v1/harness.pb.go index cab946931e..665af9b3b7 100644 --- a/contracts/gen/go/mecatl/v1/harness.pb.go +++ b/contracts/gen/go/mecatl/v1/harness.pb.go @@ -1918,12 +1918,10 @@ type ServerCapabilities struct { // (multi-provider Phase 0, S3.) ModelSelection bool `protobuf:"varint,12,opt,name=model_selection,json=modelSelection,proto3" json:"model_selection,omitempty"` // posture is the SERVER-WIDE operator posture-ladder tier ("strict"/"trusted"/ - // "auto"/"yolo"). It is CHROME ONLY — a client renders an honest "⚠ auto"/"⚠ yolo" - // badge so an operator can see the daemon's automation posture at a glance — and is + // "auto"/"yolo"). It bounds which session modes a client may cycle to and is // NEVER session state (it does not change per session; permission MODE is the // per-session knob). String passthrough, no enum on the wire (the EvNoProgress / - // StopBudget discipline). Additive: an older server leaves it empty and the client - // shows no badge (strict/trusted also show no badge). + // StopBudget discipline). Additive: an older server leaves it empty. Posture string `protobuf:"bytes,13,opt,name=posture,proto3" json:"posture,omitempty"` // worktrees is true when a WorktreeLister is wired (ListWorktrees may return a // non-empty list for a real git repo). Gates the client's /worktrees overlay — @@ -1984,8 +1982,13 @@ type ServerCapabilities struct { // execution_templates is true only when an authenticated template catalog is // wired; an eligible inventory may still be empty. ExecutionTemplates bool `protobuf:"varint,31,opt,name=execution_templates,json=executionTemplates,proto3" json:"execution_templates,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // project_trusted reports whether the server trusts its launch workspace's + // project content (rules, instructions, soul). It is an axis separate from + // the permission mode. CHROME ONLY. Additive: an older server leaves it + // unset and the client shows no trust indicator. + ProjectTrusted *bool `protobuf:"varint,32,opt,name=project_trusted,json=projectTrusted,proto3,oneof" json:"project_trusted,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServerCapabilities) Reset() { @@ -2221,6 +2224,13 @@ func (x *ServerCapabilities) GetExecutionTemplates() bool { return false } +func (x *ServerCapabilities) GetProjectTrusted() bool { + if x != nil && x.ProjectTrusted != nil { + return *x.ProjectTrusted + } + return false +} + // ListSessionMcpConnectorsRequest names an owned, broker-bound session. type ListSessionMcpConnectorsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -19795,7 +19805,7 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 0x73, 0x12, 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, 0x9a, 0x08, + 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xdc, 0x08, 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, @@ -19858,3206 +19868,3210 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 0x63, 0x70, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x2f, 0x0a, 0x13, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x14, 0x10, 0x15, - 0x4a, 0x04, 0x08, 0x15, 0x10, 0x16, 0x52, 0x0f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x61, - 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x5f, 0x6d, 0x69, 0x67, 0x72, 0x61, 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, 0xdf, 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, + 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x0f, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x20, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x14, + 0x10, 0x15, 0x4a, 0x04, 0x08, 0x15, 0x10, 0x16, 0x52, 0x0f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x5f, 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x67, 0x72, 0x61, 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, 0xdf, 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, 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, 0x12, 0x43, 0x0a, 0x1e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x64, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x72, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, + 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 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, 0x90, 0x01, 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, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x24, + 0x0a, 0x0e, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x68, 0x65, 0x6c, 0x6c, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x49, 0x6e, 0x53, + 0x68, 0x65, 0x6c, 0x6c, 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, 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, 0xb5, 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, 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, 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, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, + 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x09, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, 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, 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, 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, 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, 0x12, 0x43, 0x0a, 0x1e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x5f, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x0c, - 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 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, - 0x90, 0x01, 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, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, - 0x62, 0x75, 0x69, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x49, 0x6e, 0x53, 0x68, 0x65, - 0x6c, 0x6c, 0x22, 0x3b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 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, 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, 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, 0x72, 0x0a, 0x19, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, + 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, 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, - 0xb5, 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, 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, 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, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, - 0x0e, 0x10, 0x0f, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, - 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, 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, 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, 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, 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, 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, + 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, 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, + 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, 0x53, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, + 0x61, 0x6e, 0x63, 0x79, 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, 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, + 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, + 0x6d, 0x61, 0x74, 0x65, 0x64, 0x22, 0x8f, 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, 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, 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, 0x55, + 0x0a, 0x18, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x5f, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x16, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, + 0x70, 0x61, 0x6e, 0x63, 0x79, 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, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, + 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0c, 0x63, 0x61, 0x70, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, + 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, 0xb3, 0x01, 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, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, + 0x77, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, + 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8f, 0x02, 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, 0x42, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, + 0x06, 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, 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, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, + 0x69, 0x6c, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, + 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, + 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x04, + 0x08, 0x02, 0x10, 0x03, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 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, 0xb9, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, + 0x63, 0x74, 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, 0x18, 0x01, 0x18, 0x02, + 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, + 0x6e, 0x64, 0x52, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4b, 0x69, 0x6e, + 0x64, 0x22, 0x45, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, + 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, + 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 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, 0x53, - 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, - 0x63, 0x79, 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, 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, - 0x74, 0x65, 0x64, 0x22, 0x8f, 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, 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, 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, 0x55, 0x0a, 0x18, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x6f, - 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x16, 0x6c, 0x61, 0x74, - 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x61, - 0x6e, 0x63, 0x79, 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, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, 0x0c, 0x10, - 0x0d, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, - 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, 0xb3, 0x01, 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, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, 0x77, 0x6e, - 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, - 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8f, 0x02, 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, 0x42, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, 0x18, - 0x01, 0x18, 0x02, 0x18, 0x03, 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, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, - 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0d, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x04, 0x08, 0x02, - 0x10, 0x03, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 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, 0xb9, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, - 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0f, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, + 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, + 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x22, + 0x46, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, + 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x6b, 0x0a, 0x10, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x52, 0x75, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, + 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, + 0x75, 0x6e, 0x49, 0x64, 0x22, 0x2a, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, + 0x22, 0xc2, 0x02, 0x0a, 0x0f, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 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, 0x2f, 0x0a, 0x0f, + 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, + 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x42, 0x08, 0xba, 0x48, 0x05, 0x92, 0x01, 0x02, 0x10, 0x10, 0x52, 0x05, + 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x18, 0x40, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x3a, 0x66, 0xba, + 0x48, 0x63, 0x1a, 0x61, 0x0a, 0x11, 0x73, 0x74, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x75, 0x6e, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x74, 0x65, 0x78, 0x74, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, + 0x6f, 0x74, 0x68, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x27, 0x74, 0x68, + 0x69, 0x73, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x27, 0x20, 0x7c, 0x7c, + 0x20, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x61, 0x72, 0x74, 0x73, + 0x29, 0x20, 0x3e, 0x20, 0x30, 0x22, 0x7b, 0x0a, 0x10, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, 0x0a, 0x06, + 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, + 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, + 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, - 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, - 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, - 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, - 0x52, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x22, - 0x45, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, - 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, 0x73, 0x6b, + 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x64, 0x69, 0x63, 0x74, 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, 0x18, 0x01, - 0x18, 0x02, 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x22, 0x46, 0x0a, - 0x16, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x15, - 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x6b, 0x0a, 0x10, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, - 0x75, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, - 0x49, 0x64, 0x22, 0x2a, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x22, 0xc2, - 0x02, 0x0a, 0x0f, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, - 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, - 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, - 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x42, 0x08, 0xba, 0x48, 0x05, 0x92, 0x01, 0x02, 0x10, 0x10, 0x52, 0x05, 0x70, 0x61, - 0x72, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x18, 0x40, - 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x3a, 0x66, 0xba, 0x48, 0x63, - 0x1a, 0x61, 0x0a, 0x11, 0x73, 0x74, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x75, 0x6e, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x74, 0x65, 0x78, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x70, 0x61, 0x72, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x6f, 0x74, - 0x68, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x27, 0x74, 0x68, 0x69, 0x73, - 0x2e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x27, 0x20, 0x7c, 0x7c, 0x20, 0x73, - 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x61, 0x72, 0x74, 0x73, 0x29, 0x20, - 0x3e, 0x20, 0x30, 0x22, 0x7b, 0x0a, 0x10, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, 0x0a, 0x06, 0x72, 0x75, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, - 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, - 0x22, 0x98, 0x01, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, - 0x65, 0x65, 0x72, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, - 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, - 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x18, 0x40, - 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x16, - 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 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, + 0x18, 0x40, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x81, 0x01, + 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, 0x0a, 0x06, 0x72, + 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 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, 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, 0x50, 0x0a, 0x17, 0x50, 0x6c, 0x61, - 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x72, 0x75, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x6e, 0x52, - 0x75, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xb4, 0x09, 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, 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, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x72, 0x65, 0x66, - 0x75, 0x73, 0x65, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, - 0x66, 0x75, 0x73, 0x65, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, - 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, - 0x72, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x17, 0x70, 0x6c, - 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x52, 0x05, 0x75, 0x73, 0x61, - 0x67, 0x65, 0x22, 0x43, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x66, - 0x75, 0x73, 0x65, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 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, 0x3c, 0x0a, - 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x12, 0x10, 0x0a, - 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, - 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0xb9, 0x04, 0x0a, 0x0f, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, - 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x03, - 0x6a, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4a, - 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x73, - 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x73, 0x73, - 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x70, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6d, 0x65, + 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, 0x50, 0x0a, 0x17, 0x50, + 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x72, + 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6c, 0x61, + 0x6e, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xb4, 0x09, + 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, 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, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x72, + 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x6e, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, + 0x6c, 0x75, 0x72, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, + 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x17, + 0x70, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x52, 0x05, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x43, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, + 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 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, + 0x3c, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x12, + 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, + 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0xb9, 0x04, + 0x0a, 0x0f, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x29, + 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x73, - 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, - 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, - 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, - 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x6f, 0x72, 0x69, - 0x67, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x75, 0x6c, 0x65, 0x4f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, - 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, - 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, - 0x33, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x63, - 0x65, 0x72, 0x6e, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, - 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x52, 0x07, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xe2, 0x01, 0x0a, 0x16, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x63, 0x6f, - 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, - 0x34, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, + 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x73, 0x73, + 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x64, - 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x72, 0x61, - 0x6e, 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x72, - 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x41, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x3d, 0x0a, 0x1c, - 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, - 0x65, 0x72, 0x61, 0x67, 0x65, 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, 0x93, 0x02, 0x0a, 0x16, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, - 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, - 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, - 0x12, 0x29, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, - 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6c, 0x65, - 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, - 0x75, 0x6c, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x3e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, - 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, + 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, + 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, + 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x22, 0xd0, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2e, 0x0a, - 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, - 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, - 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, - 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 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, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, - 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x12, - 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, - 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb6, 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, 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, 0x34, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, - 0x69, 0x63, 0x74, 0x18, 0x06, 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, 0x16, - 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x05, - 0x10, 0x06, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 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, + 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x64, 0x69, 0x73, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, + 0x72, 0x61, 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x75, 0x6c, + 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, + 0x64, 0x12, 0x33, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0b, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x52, 0x08, 0x63, 0x6f, + 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, + 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xe2, 0x01, 0x0a, 0x16, 0x47, 0x75, + 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, + 0x64, 0x12, 0x34, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, + 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x29, 0x0a, + 0x10, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x41, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x3d, + 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, + 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 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, 0x93, 0x02, + 0x0a, 0x16, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, + 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, + 0x73, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x12, 0x0a, + 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, + 0x6c, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x72, 0x75, 0x6c, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x3e, 0x0a, 0x0a, 0x69, + 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0a, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x22, 0xd0, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, + 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x28, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x65, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, + 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, + 0x69, 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, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, + 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, + 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, + 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, + 0x65, 0x78, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb6, 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, 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, 0x34, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x06, 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, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, + 0x08, 0x05, 0x10, 0x06, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 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, 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, 0xb8, 0x01, - 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, 0x12, 0x38, - 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x09, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x22, 0xb8, 0x03, 0x0a, 0x0f, 0x52, 0x6f, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, - 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, - 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x63, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, - 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, - 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x61, 0x6e, 0x64, 0x69, - 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, - 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x32, - 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, - 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x11, 0x6d, 0x69, - 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x88, - 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x12, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73, - 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, - 0x69, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x09, 0x6d, 0x69, 0x73, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x72, - 0x65, 0x61, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x0d, 0x0a, - 0x0b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x15, 0x0a, 0x13, - 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, - 0x6e, 0x63, 0x65, 0x22, 0x81, 0x06, 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, - 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, - 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, - 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, - 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, - 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, - 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x03, 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, - 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0xc5, 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, 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, 0x12, 0x2b, 0x0a, - 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, - 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, - 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x22, 0xb5, 0x07, 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, + 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, + 0xb8, 0x01, 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, + 0x12, 0x38, 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, + 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x22, 0xb8, 0x03, 0x0a, 0x0f, 0x52, + 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x6f, + 0x64, 0x65, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x11, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, + 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x61, 0x6e, + 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0a, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, + 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, + 0x12, 0x32, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x11, + 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x2d, + 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x69, + 0x73, 0x73, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1d, 0x0a, + 0x0a, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x6d, 0x69, 0x73, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x6e, 0x42, + 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x15, + 0x0a, 0x13, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x64, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x81, 0x06, 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, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, + 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, - 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, + 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, + 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, - 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 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, 0xd1, 0x01, 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, 0x12, 0x3f, 0x0a, 0x09, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x63, 0x6f, - 0x70, 0x65, 0x52, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, - 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, - 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0xc1, 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, 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, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, - 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x22, 0x70, 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, 0x12, - 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 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, 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, + 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x03, 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, 0x12, 0x4a, 0x0a, + 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, + 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, + 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, + 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, + 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, + 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc5, 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, 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, 0x12, + 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, + 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x69, + 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x22, 0xb5, 0x07, 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1a, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, + 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, + 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, + 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, + 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, + 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, + 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 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, 0xd1, 0x01, 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, 0x12, 0x3f, + 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, + 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x52, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x12, + 0x1c, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, + 0x08, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0xc1, 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, 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, 0x4a, 0x04, 0x08, 0x05, + 0x10, 0x06, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x22, 0x70, 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, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 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, 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, 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, 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, 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, + 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, 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, 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, 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, 0x5b, 0x0a, 0x0d, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, - 0x65, 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, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, - 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x22, 0x34, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x22, 0x48, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x1b, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x66, - 0x69, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x15, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 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, 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, + 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, 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, 0x5b, 0x0a, 0x0d, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, + 0x69, 0x6c, 0x65, 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, 0x12, 0x0a, 0x04, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, + 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x22, 0x34, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x22, 0x48, 0x0a, 0x16, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x1b, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x15, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, + 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 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, 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, - 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, 0xdd, 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, - 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, - 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x64, 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, + 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, 0xdd, 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, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x5f, 0x63, 0x61, 0x63, + 0x68, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, + 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 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, 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, 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, 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, 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, + 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, 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, + 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, 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, 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, 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, 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, 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, + 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, 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, 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, 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, + 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, 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, + 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, 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, + 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, 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, - 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, + 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, 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, + 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, 0x02, + 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, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, + 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, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, + 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, 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, + 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, 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, 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, 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, 0xbe, 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, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, - 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x55, 0x54, - 0x4f, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, - 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x59, 0x4f, 0x4c, 0x4f, 0x10, 0x05, 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, 0x80, 0x01, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, - 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, - 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x19, 0x0a, - 0x15, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x49, - 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x47, 0x55, 0x41, 0x52, - 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, - 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xaa, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x24, - 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, - 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, - 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x43, - 0x45, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, - 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, - 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x23, - 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, - 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x53, 0x4f, 0x4c, 0x56, 0x45, - 0x44, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x20, 0x47, - 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, - 0x54, 0x45, 0x10, 0x01, 0x12, 0x2c, 0x0a, 0x28, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, - 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x45, - 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, - 0x10, 0x02, 0x2a, 0xd0, 0x02, 0x0a, 0x14, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, - 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x21, 0x47, - 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 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, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, - 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x58, 0x45, 0x43, - 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, - 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, - 0x53, 0x4b, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x29, 0x0a, 0x25, 0x47, + 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, 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, 0xbe, + 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, 0x12, 0x18, 0x0a, 0x14, 0x50, + 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, + 0x55, 0x54, 0x4f, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, + 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x59, 0x4f, 0x4c, 0x4f, 0x10, 0x05, 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, 0x80, 0x01, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, + 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, + 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, + 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, + 0x19, 0x0a, 0x15, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, + 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x47, 0x55, + 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x50, 0x45, 0x52, 0x4d, + 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xaa, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, + 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, + 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, + 0x43, 0x43, 0x45, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x47, + 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, + 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, + 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, + 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x53, 0x4f, 0x4c, + 0x56, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, + 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, + 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, + 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x50, + 0x4c, 0x45, 0x54, 0x45, 0x10, 0x01, 0x12, 0x2c, 0x0a, 0x28, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, + 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, + 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, + 0x52, 0x45, 0x10, 0x02, 0x2a, 0xd0, 0x02, 0x0a, 0x14, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, + 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, + 0x21, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 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, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, + 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x58, + 0x45, 0x43, 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, + 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x41, 0x53, 0x4b, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x29, 0x0a, + 0x25, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, + 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x48, 0x4f, 0x4c, 0x44, 0x5f, + 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x47, 0x55, 0x41, 0x52, + 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, + 0x10, 0x04, 0x12, 0x1e, 0x0a, 0x1a, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, + 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, + 0x10, 0x05, 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, + 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x53, 0x53, + 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, 0x2a, 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x48, 0x4f, 0x4c, 0x44, 0x5f, 0x52, 0x45, - 0x53, 0x55, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, - 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x04, - 0x12, 0x1e, 0x0a, 0x1a, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, - 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x05, - 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, - 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x5f, 0x41, - 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, 0x2a, 0x0a, 0x26, 0x47, 0x55, 0x41, - 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x45, 0x5f, 0x57, 0x41, 0x52, 0x4e, - 0x49, 0x4e, 0x47, 0x10, 0x07, 0x2a, 0x90, 0x01, 0x0a, 0x15, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, - 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, - 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x47, 0x55, 0x41, 0x52, - 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, - 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, - 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x52, - 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x02, 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, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x45, 0x5f, 0x57, 0x41, + 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x2a, 0x90, 0x01, 0x0a, 0x15, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, + 0x64, 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, + 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x47, 0x55, + 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x2a, + 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, + 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, + 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x02, 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, - 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, 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, 0x9c, - 0x39, 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, 0x6d, 0x0a, 0x16, 0x4c, 0x69, - 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x73, 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, 0x6a, 0x0a, 0x15, - 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, - 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, - 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, - 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x47, - 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, - 0x65, 0x74, 0x61, 0x69, 0x6c, 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, + 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, 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, 0x9c, 0x39, 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, 0x6d, 0x0a, 0x16, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x73, 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, 0x6a, + 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, + 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, + 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x47, 0x65, + 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 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, 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, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, - 0x6b, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, - 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, - 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 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, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, + 0x41, 0x73, 0x6b, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, - 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x12, - 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, - 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, + 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, + 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, + 0x09, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, - 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, + 0x6e, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, + 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, + 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, - 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, + 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 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, 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, + 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, 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, + 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, - 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, 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, 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, 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, + 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, 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, 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, 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, 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, + 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, 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, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, - 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 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, + 0x69, 0x6c, 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, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, + 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x12, + 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, + 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 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, 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, + 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, 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, 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, - 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, + 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, 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, - 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, + 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, 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, 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, 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, + 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, 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, 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, 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, - 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, + 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, 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, + 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, 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, 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, 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, + 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, 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, - 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, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 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 ( @@ -23735,6 +23749,7 @@ func file_mecatl_v1_harness_proto_init() { if File_mecatl_v1_harness_proto != nil { return } + file_mecatl_v1_harness_proto_msgTypes[13].OneofWrappers = []any{} file_mecatl_v1_harness_proto_msgTypes[33].OneofWrappers = []any{} file_mecatl_v1_harness_proto_msgTypes[57].OneofWrappers = []any{} file_mecatl_v1_harness_proto_msgTypes[59].OneofWrappers = []any{} diff --git a/contracts/proto/mecatl/v1/harness.proto b/contracts/proto/mecatl/v1/harness.proto index 6a4171c0b9..d8fe043e37 100644 --- a/contracts/proto/mecatl/v1/harness.proto +++ b/contracts/proto/mecatl/v1/harness.proto @@ -810,12 +810,10 @@ message ServerCapabilities { // (multi-provider Phase 0, S3.) bool model_selection = 12; // posture is the SERVER-WIDE operator posture-ladder tier ("strict"/"trusted"/ - // "auto"/"yolo"). It is CHROME ONLY — a client renders an honest "⚠ auto"/"⚠ yolo" - // badge so an operator can see the daemon's automation posture at a glance — and is + // "auto"/"yolo"). It bounds which session modes a client may cycle to and is // NEVER session state (it does not change per session; permission MODE is the // per-session knob). String passthrough, no enum on the wire (the EvNoProgress / - // StopBudget discipline). Additive: an older server leaves it empty and the client - // shows no badge (strict/trusted also show no badge). + // StopBudget discipline). Additive: an older server leaves it empty. string posture = 13; // worktrees is true when a WorktreeLister is wired (ListWorktrees may return a // non-empty list for a real git repo). Gates the client's /worktrees overlay — @@ -878,6 +876,11 @@ message ServerCapabilities { // execution_templates is true only when an authenticated template catalog is // wired; an eligible inventory may still be empty. bool execution_templates = 31; + // project_trusted reports whether the server trusts its launch workspace's + // project content (rules, instructions, soul). It is an axis separate from + // the permission mode. CHROME ONLY. Additive: an older server leaves it + // unset and the client shows no trust indicator. + optional bool project_trusted = 32; } // ListSessionMcpConnectorsRequest names an owned, broker-bound session. diff --git a/internal/adapter/server/http.go b/internal/adapter/server/http.go index 9239208251..e39d928af8 100644 --- a/internal/adapter/server/http.go +++ b/internal/adapter/server/http.go @@ -2769,6 +2769,10 @@ func modeFromString(s string) session.PermissionMode { return session.ModeAccept case "default": return session.ModeDefault + case "auto": + return session.ModeAuto + case "yolo": + return session.ModeYolo default: return "" } diff --git a/internal/adapter/server/mapper.go b/internal/adapter/server/mapper.go index 1869526842..53a16c1f05 100644 --- a/internal/adapter/server/mapper.go +++ b/internal/adapter/server/mapper.go @@ -1126,6 +1126,10 @@ func modeToProto(m session.PermissionMode) mecatlv1.PermissionMode { return mecatlv1.PermissionMode_PERMISSION_MODE_PLAN case session.ModeAccept: return mecatlv1.PermissionMode_PERMISSION_MODE_ACCEPT_EDITS + case session.ModeAuto: + return mecatlv1.PermissionMode_PERMISSION_MODE_AUTO + case session.ModeYolo: + return mecatlv1.PermissionMode_PERMISSION_MODE_YOLO case session.ModeDefault: return mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT default: @@ -1398,6 +1402,10 @@ func modeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { return session.ModePlan case mecatlv1.PermissionMode_PERMISSION_MODE_ACCEPT_EDITS: return session.ModeAccept + case mecatlv1.PermissionMode_PERMISSION_MODE_AUTO: + return session.ModeAuto + case mecatlv1.PermissionMode_PERMISSION_MODE_YOLO: + return session.ModeYolo case mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT, mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED: return session.ModeDefault default: diff --git a/internal/adapter/server/mode_admission_test.go b/internal/adapter/server/mode_admission_test.go new file mode 100644 index 0000000000..7a24541a26 --- /dev/null +++ b/internal/adapter/server/mode_admission_test.go @@ -0,0 +1,245 @@ +package server_test + +import ( + "context" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + 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/session" + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +// modeAdmissionService builds a Service with the given permission-mode +// ceiling, default mode, and enforcing-checker state. +func modeAdmissionService(t *testing.T, ceiling, defaultMode session.PermissionMode, checker bool) *server.Service { + t.Helper() + llm := mockllm.New() + svc, err := newPlacementTeamTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{ + LLM: llm, + Catalog: tool.NewCatalog(), + Policy: permpolicy.NewPolicy(allowRules(), nil), + Model: "test-model", + }), + Store: memstore.New(), + PlacementProvider: testPlacementProvider{}, + PlacementScope: "test", + Now: func() time.Time { return time.Unix(0, 0) }, + DefaultCapabilities: llm.Capabilities(), + DefaultMode: defaultMode, + MaxAllowedMode: ceiling, + EnforcingCheckerConfigured: checker, + }) + if err != nil { + t.Fatalf("new service: %v", err) + } + return svc +} + +// TestGRPCAutoYoloModesRoundTrip pins that AUTO and YOLO survive the gRPC +// boundary on CreateSession, SetMode, and the session read-back instead of +// collapsing to DEFAULT. +func TestGRPCAutoYoloModesRoundTrip(t *testing.T) { + svc := modeAdmissionService(t, session.ModeYolo, session.ModeDefault, true) + client, cleanup := dialGRPC(t, svc) + defer cleanup() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + for _, tc := range []struct { + proto mecatlv1.PermissionMode + want session.PermissionMode + }{ + {mecatlv1.PermissionMode_PERMISSION_MODE_AUTO, session.ModeAuto}, + {mecatlv1.PermissionMode_PERMISSION_MODE_YOLO, session.ModeYolo}, + } { + cs, err := client.CreateSession(ctx, &mecatlv1.CreateSessionRequest{Mode: tc.proto}) + if err != nil { + t.Fatalf("CreateSession(%s): %v", tc.proto, err) + } + sess, err := svc.GetSession(ctx, session.SessionID(cs.GetSessionId())) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if sess.Mode != tc.want { + t.Errorf("CreateSession(%s) started in %q, want %q", tc.proto, sess.Mode, tc.want) + } + got, err := client.GetSession(ctx, &mecatlv1.GetSessionRequest{SessionId: cs.GetSessionId()}) + if err != nil { + t.Fatalf("GetSession RPC: %v", err) + } + if got.GetSession().GetMode() != tc.proto { + t.Errorf("GetSession mode = %s, want %s", got.GetSession().GetMode(), tc.proto) + } + + plain, err := client.CreateSession(ctx, &mecatlv1.CreateSessionRequest{Mode: mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT}) + if err != nil { + t.Fatalf("CreateSession(DEFAULT): %v", err) + } + set, err := client.SetMode(ctx, &mecatlv1.SetModeRequest{SessionId: plain.GetSessionId(), Mode: tc.proto}) + if err != nil { + t.Fatalf("SetMode(%s): %v", tc.proto, err) + } + if set.GetSession().GetMode() != tc.proto { + t.Errorf("SetMode(%s) reply mode = %s", tc.proto, set.GetSession().GetMode()) + } + } +} + +// TestGRPCModeAdmissionRefusals pins that CreateSession and SetMode share the +// ceiling and enforcing-checker admission, refusing with InvalidArgument. +func TestGRPCModeAdmissionRefusals(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + for _, tc := range []struct { + name string + ceiling session.PermissionMode + checker bool + mode mecatlv1.PermissionMode + reason string + }{ + {"yolo above strict ceiling", session.ModeDefault, true, mecatlv1.PermissionMode_PERMISSION_MODE_YOLO, "exceeds the server ceiling"}, + {"auto above strict ceiling", session.ModeAccept, true, mecatlv1.PermissionMode_PERMISSION_MODE_AUTO, "exceeds the server ceiling"}, + {"auto without checker", session.ModeYolo, false, mecatlv1.PermissionMode_PERMISSION_MODE_AUTO, "enforcing guardrails checker"}, + } { + t.Run(tc.name, func(t *testing.T) { + svc := modeAdmissionService(t, tc.ceiling, session.ModeDefault, tc.checker) + client, cleanup := dialGRPC(t, svc) + defer cleanup() + + _, err := client.CreateSession(ctx, &mecatlv1.CreateSessionRequest{Mode: tc.mode}) + if status.Code(err) != codes.InvalidArgument || !strings.Contains(err.Error(), tc.reason) { + t.Fatalf("CreateSession err = %v, want InvalidArgument naming %q", err, tc.reason) + } + + cs, err := client.CreateSession(ctx, &mecatlv1.CreateSessionRequest{Mode: mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT}) + if err != nil { + t.Fatalf("CreateSession(DEFAULT): %v", err) + } + _, err = client.SetMode(ctx, &mecatlv1.SetModeRequest{SessionId: cs.GetSessionId(), Mode: tc.mode}) + if status.Code(err) != codes.InvalidArgument || !strings.Contains(err.Error(), tc.reason) { + t.Fatalf("SetMode err = %v, want InvalidArgument naming %q", err, tc.reason) + } + sess, err := svc.GetSession(ctx, session.SessionID(cs.GetSessionId())) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if sess.Mode != session.ModeDefault { + t.Fatalf("refused SetMode changed mode to %q", sess.Mode) + } + }) + } +} + +// TestOperatorDefaultAutoAdmittedWithoutChecker pins that the operator's +// configured default mode stays admissible without an enforcing checker (the +// operator chose it; startup WARNs), both for an unspecified create and for +// an explicit request of that same mode. +func TestOperatorDefaultAutoAdmittedWithoutChecker(t *testing.T) { + svc := modeAdmissionService(t, session.ModeAuto, session.ModeAuto, false) + ctx := context.Background() + for _, mode := range []session.PermissionMode{"", session.ModeAuto} { + sess, err := svc.CreateSession(ctx, mode, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession(%q): %v", mode, err) + } + if sess.Mode != session.ModeAuto { + t.Fatalf("CreateSession(%q) mode = %q, want auto", mode, sess.Mode) + } + } +} + +// TestHTTPAutoYoloModes pins the HTTP mode mapping and the shared admission. +func TestHTTPAutoYoloModes(t *testing.T) { + decode := func(resp *http.Response) (int, string) { + defer resp.Body.Close() + var out struct { + SessionID string `json:"session_id"` + Mode string `json:"mode"` + } + _ = json.NewDecoder(resp.Body).Decode(&out) + if out.SessionID == "" { + return resp.StatusCode, "" + } + return resp.StatusCode, out.SessionID + " " + out.Mode + } + post := func(t *testing.T, url, body string) (int, string) { + t.Helper() + resp, err := http.Post(url, "application/json", strings.NewReader(body)) + if err != nil { + t.Fatalf("POST %s: %v", url, err) + } + return decode(resp) + } + + srv := httptest.NewServer(server.NewHTTPHandler(modeAdmissionService(t, session.ModeYolo, session.ModeDefault, true))) + defer srv.Close() + for _, mode := range []string{"auto", "yolo"} { + code, got := post(t, srv.URL+"/v1/sessions", `{"mode":"`+mode+`"}`) + if code != http.StatusCreated || got == "" { + t.Fatalf("create %s = %d %q, want 201", mode, code, got) + } + id := strings.Fields(got)[0] + resp, err := http.Get(srv.URL + "/v1/sessions/" + id) + if err != nil { + t.Fatalf("GET session: %v", err) + } + if code, got = decode(resp); code != http.StatusOK || !strings.HasSuffix(got, " "+mode) { + t.Fatalf("created %s session reads back %d %q", mode, code, got) + } + code, got = post(t, srv.URL+"/v1/sessions/"+id+"/mode", `{"mode":"default"}`) + if code != http.StatusOK || !strings.HasSuffix(got, " default") { + t.Fatalf("set default = %d %q", code, got) + } + code, got = post(t, srv.URL+"/v1/sessions/"+id+"/mode", `{"mode":"`+mode+`"}`) + if code != http.StatusOK || !strings.HasSuffix(got, " "+mode) { + t.Fatalf("set %s = %d %q", mode, code, got) + } + } + + strict := httptest.NewServer(server.NewHTTPHandler(modeAdmissionService(t, session.ModeDefault, session.ModeDefault, true))) + defer strict.Close() + if code, _ := post(t, strict.URL+"/v1/sessions", `{"mode":"yolo"}`); code != http.StatusBadRequest { + t.Fatalf("create yolo above ceiling = %d, want 400", code) + } +} + +// TestApprovePlanRefusesAutoYoloTarget pins that plan approval cannot flip a +// session into auto or yolo: it refuses instead of silently denying the plan. +func TestApprovePlanRefusesAutoYoloTarget(t *testing.T) { + for _, target := range []session.PermissionMode{session.ModeAuto, session.ModeYolo} { + llm := mockllm.New(mockllm.ToolCallTurn(call("c1", "PresentPlan", `{"note":"step 1"}`))) + svc := planApprovalService(t, llm, allowRules()) + sess, err := svc.CreateSession(context.Background(), session.ModePlan, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + _, finishParked := parkPlanAsk(t, svc, sess.ID) + _, err = svc.ApprovePlan(context.Background(), sess.ID, target, "") + if !errors.Is(err, server.ErrInvalidArgument) { + t.Fatalf("ApprovePlan(%s) err = %v, want ErrInvalidArgument", target, err) + } + got, err := svc.GetSession(context.Background(), sess.ID) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if got.State != session.StateAwaiting { + t.Fatalf("refused ApprovePlan(%s) consumed the plan ask: state %q", target, got.State) + } + finishParked() + } +} diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index ba66c53727..c73f01b5e0 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -652,6 +652,10 @@ type Config struct { // Empty (the zero value / an unconfigured child service) yields no badge. String // passthrough — no enum on the wire (the EvNoProgress/StopBudget discipline). Posture string + // ProjectTrusted is the effective project-trust decision for the launch + // workspace, projected into the ServerCapabilities echo as CHROME ONLY. nil + // (an unconfigured child service) leaves the echo unset. + ProjectTrusted *bool // DeploymentID is an optional, opaque, operator-set label for this deployment, // surfaced on GetServerInfo. It is empty by default and is NEVER derived from // hostname, pod name, or environment: infrastructure topology is not something @@ -2757,6 +2761,9 @@ func (s *Service) createSession(ctx context.Context, mode session.PermissionMode if mode == "" { mode = s.cfg.DefaultMode } + if err := s.admitMode(mode); err != nil { + return nil, err + } // Fill any UNSET (zero) limit field from the injected defaults, per-field. An // all-zero Limits inherits every default (so a default session cannot run // unbounded); a Limits that pins only some caps keeps those and inherits the @@ -3275,6 +3282,7 @@ func (s *Service) capabilities() *mecatlv1.ServerCapabilities { Image: pcaps.Image, Audio: pcaps.Audio, Posture: s.cfg.Posture, + ProjectTrusted: s.cfg.ProjectTrusted, Worktrees: s.placementDiscoveryAvailable(), Reflection: s.cfg.ReflectSession != nil, LearningProposals: s.cfg.Proposals != nil, @@ -4754,13 +4762,8 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio if mode == "" { return nil, fmt.Errorf("%w: mode is required", ErrInvalidArgument) } - // Ceiling check: refuse modes that exceed the server's configured ceiling. - if s.cfg.MaxAllowedMode != "" && !modeWithinCeiling(mode, s.cfg.MaxAllowedMode) { - return nil, fmt.Errorf("%w: mode %q exceeds the server ceiling %q; the server must be relaunched with a higher --permission-mode to allow it", ErrInvalidArgument, mode, s.cfg.MaxAllowedMode) - } - // Checker check: auto mode requires an enforcing checker. - if mode == session.ModeAuto && !s.hasEnforcingChecker() { - return nil, fmt.Errorf("%w: mode %q requires an enforcing guardrails checker; configure one with --guardrails-model or bind the guardrail model slot, or use yolo for gate-free autonomous operation", ErrInvalidArgument, mode) + if err := s.admitMode(mode); err != nil { + return nil, err } // Ownership is established before caller-selected coordination, then // revalidated under runEntryMu before and after lease acquisition. @@ -4818,6 +4821,25 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio return sess, nil } +// admitMode is the single admission check for a caller-requested session mode, +// shared by CreateSession, SetMode, and schedule fires (which create through +// CreateSession). A mode above the server ceiling is refused, and auto requires +// an enforcing guardrails checker. The operator-configured DefaultMode is +// always admissible: the operator chose it at startup (where a missing checker +// is narrated as a WARN), so a session may start in it and return to it. +func (s *Service) admitMode(mode session.PermissionMode) error { + if modeRank(mode) == 0 { + return fmt.Errorf("%w: unknown permission mode %q", ErrInvalidArgument, mode) + } + if s.cfg.MaxAllowedMode != "" && !modeWithinCeiling(mode, s.cfg.MaxAllowedMode) { + return fmt.Errorf("%w: mode %q exceeds the server ceiling %q; the server must be relaunched with a higher --permission-mode to allow it", ErrInvalidArgument, mode, s.cfg.MaxAllowedMode) + } + if mode == session.ModeAuto && mode != s.cfg.DefaultMode && !s.hasEnforcingChecker() { + return fmt.Errorf("%w: mode %q requires an enforcing guardrails checker; configure one with --guardrails-model or bind the guardrail model slot, or use yolo for gate-free autonomous operation", ErrInvalidArgument, mode) + } + return nil +} + // modeWithinCeiling reports whether mode is at or below ceiling in the // permission-mode ordering: plan < default < accept-edits < auto < yolo. func modeWithinCeiling(mode, ceiling session.PermissionMode) bool { @@ -7695,7 +7717,11 @@ func (s *Service) approvePlan(ctx context.Context, id session.SessionID, targetM if !ok || ask.Origin != session.ApprovalOriginPlan { return nil, fmt.Errorf("%w: session %q is not awaiting a plan-approval ask", ErrNotAwaitingPlan, id) } - // (3) targetMode → verdict. + // (3) targetMode → verdict. Plan approval can flip only to default or + // accept-edits; refuse auto/yolo rather than silently treating them as deny. + if targetMode == session.ModeAuto || targetMode == session.ModeYolo { + return nil, fmt.Errorf("%w: plan approval cannot switch to mode %q; approve into default or accept-edits, then change the mode with SetMode", ErrInvalidArgument, targetMode) + } verdict, allowContinuation := planVerdictForMode(targetMode) // The merged event channel. Buffered to match a Run's own buffer (64) so a diff --git a/internal/app/build.go b/internal/app/build.go index 14577029fd..932ba3f56c 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -880,7 +880,11 @@ type Config struct { guardrailConfigured bool guardrailDetails *server.ReviewDetailRegistry guardrailHealth *guardrailRouteHealth - planApprovals *planApprovalReceipts + // guardrailSessionMode is the session mode an engine's guardrail rules are + // compiled for (set per session by the session-engine factory). Empty means + // the shared engine, whose rules follow the process posture. + guardrailSessionMode session.PermissionMode + planApprovals *planApprovalReceipts // Slash commands: directory of .md templates; EnableCommands turns on the // default directories when CommandsDir is empty. @@ -2111,7 +2115,6 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { checkerRefusal(cfg, checkerConfigured) cfg = resolveAskReviewerDefault(cfg) narratePermissionMode(cfg, checkerConfigured) - checker, _ := checkerState(cfg, checkerConfigured) // Emit the build-once composition facts (token counter / compaction strategy / // slash commands) EXACTLY ONCE here, through the injected Diagnostics — keyed to // the resolved MAIN model. The per-derivation builders do not log these (they @@ -2462,7 +2465,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // server's own ModeDefault. DefaultMode: cfg.DefaultSessionMode, MaxAllowedMode: cfg.MaxAllowedMode, - EnforcingCheckerConfigured: checker == checkerEnforcing, + EnforcingCheckerConfigured: autoCheckerEnforcing(cfg, checkerConfigured), BuildID: buildinfo.BuildID, ServerImplementation: cfg.ServerImplementation, // GetServerInfo looks up only a caller-selected, already-known provider @@ -2592,6 +2595,9 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // ServerCapabilities echo as CHROME (a client renders a "⚠ auto"/"⚠ yolo" badge). // NOT session state — see server.Config.Posture. Posture: cfg.Posture.String(), + // ProjectTrusted: the effective trust fold for the launch workspace (flag, + // declared, remembered, or the interactive posture floor), CHROME ONLY. + ProjectTrusted: &cfg.TrustProject, // DeploymentID: the operator-set, opaque deployment label surfaced on // GetCompatibilityInfo. It is passed through VERBATIM and is never // derived here from hostname, pod name, or environment — an inferred label @@ -3429,6 +3435,7 @@ func sessionEngineFactoryWithTools( ) server.SessionEngineWithToolsFactory { build := func(ctx context.Context, sel server.ProviderSelector, specs []mcp.ServerConfig, profile server.SessionProfile, workspace string, mode session.PermissionMode, sessionTools []tool.Tool, sessionToolKeys []string) (server.SessionEngineResult, error) { cfg := cfg // Permission resolver overrides belong to this invocation, not the shared closure. + cfg.guardrailSessionMode = mode runtimeAssets := mcpCatalogAssets(ctx, assets) runtimeRevision := mcpRuntimeRevision(ctx) // Pin the CHILD permission resolver to THIS session's base root (issue diff --git a/internal/app/guardrails.go b/internal/app/guardrails.go index 0602d3ff63..31b32ee1d3 100644 --- a/internal/app/guardrails.go +++ b/internal/app/guardrails.go @@ -359,6 +359,7 @@ func guardrailCoverageFor(cfg Config, sess *session.Session) server.GuardrailCov if !coverage.Enabled || sess == nil { return coverage } + cfg.guardrailSessionMode = sess.Mode specs, _ := effectiveGuardrailSpecs(cfg) rules, ok := compileGuardrailRules(cfg, specs) if !ok { @@ -477,18 +478,31 @@ func effectiveGuardrailSpecs(cfg Config) (specs []modelhook.RuleSpec, usedDefaul return out, true } -// demoteForPosture demotes the enforcing guardrail block mode to advisory -// under posture YOLO ONLY (CC bypassPermissions parity). +// demoteForPosture demotes the enforcing guardrail block mode to advisory for +// the gate-free yolo tier ONLY (CC bypassPermissions parity). A per-session +// engine (cfg.guardrailSessionMode set) is demoted only when its session is in +// yolo mode, so an auto session on a yolo server keeps an enforcing checker; +// the shared engine follows the process posture, and sessions whose mode +// disagrees with it are promoted to a per-session engine (modeNeedsEngine). // strict/trusted/auto keep the configured mode — under auto the approve-once ask IS // the enforcement behaviour. It is the SINGLE posture→mode coupling point so the // default-set and operator-rule branches cannot drift. func demoteForPosture(cfg Config, mode string) string { - if cfg.Posture < PostureYolo { + if !guardrailsDemoted(cfg) { return mode } return string(modelhook.ModeAdvisory) } +// guardrailsDemoted reports whether the engine cfg describes runs its +// guardrail rules advisory-only. +func guardrailsDemoted(cfg Config) bool { + if cfg.guardrailSessionMode != "" { + return cfg.guardrailSessionMode == session.ModeYolo + } + return cfg.Posture >= PostureYolo +} + // guardrailsConfigured reports whether guardrails are switched on: a checker model // is configured — via --guardrails-model OR a bound `guardrail` model slot (configure = // enable, the same model as the subagent router) — AND the master kill-switch diff --git a/internal/app/guardrails_approve_once_e2e_test.go b/internal/app/guardrails_approve_once_e2e_test.go index 962418f048..6b6ea0146d 100644 --- a/internal/app/guardrails_approve_once_e2e_test.go +++ b/internal/app/guardrails_approve_once_e2e_test.go @@ -290,6 +290,42 @@ func TestGuardrailApproveOnceE2EHeadlessTerminalBlock(t *testing.T) { } } +// Posture YOLO, session switched to AUTO: the yolo demotion is per session mode, +// so the auto session is admitted (an enforcing checker exists for it) and its +// guardrail blocks — headless, a terminal block, and the tool does not run. +func TestGuardrailE2EYoloServerAutoSessionEnforces(t *testing.T) { + ctx := context.Background() + cfg := guardrailE2ECfg(t, false, PostureYolo, "touch "+guardrailMarker) + built, err := buildIsolated(t, ctx, cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + sess, err := built.Service.CreateSession(ctx, session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + if _, err := built.Service.SetMode(ctx, sess.ID, session.ModeAuto); err != nil { + t.Fatalf("SetMode(auto) on a yolo server with a checker: %v", err) + } + srv := httptest.NewServer(server.NewHTTPHandler(built.Service)) + defer srv.Close() + + evs := driveGuardrailPrompt(t, srv.URL, string(sess.ID), "merge it", nil) + var blocked bool + for _, ev := range evs { + if ev.Type == "tool.result" && ev.ToolResult.IsError && strings.Contains(ev.ToolResult.Content, "guardrail") { + blocked = true + } + } + if !blocked { + t.Fatal("an auto session on a yolo server must keep an enforcing checker — no guardrail block surfaced") + } + if markerExists(t, cfg.Workspace) { + t.Fatal("the enforcing auto-session block must NOT execute the Shell command — but the marker file exists") + } +} + // Posture YOLO: guardrails demote to advisory — the tool RUNS, no ask, no block. func TestGuardrailApproveOnceE2EYoloAdvisory(t *testing.T) { ctx := context.Background() diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 2d5c828d0c..75a56bf78d 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -41,9 +41,13 @@ type PermissionModeToken struct { // auto or yolo) are deliberately absent: allow-all already permits edits. // trusted and trusted-accept-edits are dropped as modes; project trust is // raised via --trust-project combined with any mode. +// +// The strict tiers share one ceiling, accept-edits: plan, default, and +// accept-edits are all reachable on a strict server (the TUI cycles through +// them live), so the ceiling only bounds the allow-all modes. var permissionModeTable = []PermissionModeToken{ - {Name: "plan", Posture: PostureStrict, SessionMode: session.ModePlan, MaxMode: session.ModePlan}, - {Name: "default", Posture: PostureStrict, SessionMode: session.ModeDefault, MaxMode: session.ModeDefault}, + {Name: "plan", Posture: PostureStrict, SessionMode: session.ModePlan, MaxMode: session.ModeAccept}, + {Name: "default", Posture: PostureStrict, SessionMode: session.ModeDefault, MaxMode: session.ModeAccept}, {Name: "accept-edits", Posture: PostureStrict, SessionMode: session.ModeAccept, MaxMode: session.ModeAccept}, // auto and yolo: sessions start in the named mode. The allow-all and // loose-substitution behaviors are injected at evaluation time by @@ -140,8 +144,8 @@ func postureToSessionModes(p Posture) (session.PermissionMode, session.Permissio return session.ModeAuto, session.ModeAuto case PostureYolo: return session.ModeYolo, session.ModeYolo - default: // PostureStrict, PostureTrusted → default mode - return session.ModeDefault, session.ModeDefault + default: // PostureStrict, PostureTrusted → default mode, strict ceiling + return session.ModeDefault, session.ModeAccept } } @@ -164,7 +168,7 @@ func checkerRefusal(cfg Config, checkerConfigured bool) { // yoloCheckerAdvisoryNote states what a configured checker does NOT do at the // gate-free tier, where demoteForPosture makes it advisory. Shared by the // refusal and the startup line so they cannot disagree. -const yoloCheckerAdvisoryNote = "At yolo a configured checker is observability-only: it has no pre-tool veto, no approve-once human ask, and no fail-closed on checker failure, so a checker outage looks the same as a clean result" +const yoloCheckerAdvisoryNote = "In yolo-mode sessions a configured checker is observability-only: it has no pre-tool veto, no approve-once human ask, and no fail-closed on checker failure, so a checker outage looks the same as a clean result. Sessions switched to another mode, including auto, keep it enforcing" // headlessTrustRefusal is the headless admission gate. // It runs AFTER resolveTrust, so any legitimate trust source satisfies it, and @@ -222,7 +226,7 @@ func checkerState(cfg Config, configured bool) (state, reason string) { case !configured: return checkerDisabled, "no checker configured" case cfg.MaxAllowedMode == session.ModeYolo: - return checkerAdvisory, "demoted: yolo mode has no enforcing checker" + return checkerAdvisory, "demoted in yolo-mode sessions; other modes keep it enforcing" } specs, _ := effectiveGuardrailSpecs(cfg) if highestSeverityGuardrailMode(specs) == string(modelhook.ModeAdvisory) { @@ -231,6 +235,19 @@ func checkerState(cfg Config, configured bool) (state, reason string) { return checkerEnforcing, "" } +// autoCheckerEnforcing reports whether an auto session runs with an enforcing +// checker. Unlike checkerState it ignores the yolo demotion, which applies per +// session mode (guardrailsDemoted): an auto session on a yolo server still +// compiles its rules enforcing. +func autoCheckerEnforcing(cfg Config, configured bool) bool { + if cfg.GuardrailsDisabled || !configured { + return false + } + cfg.guardrailSessionMode = session.ModeAuto + specs, _ := effectiveGuardrailSpecs(cfg) + return highestSeverityGuardrailMode(specs) != string(modelhook.ModeAdvisory) +} + // reviewerState reports the subagent ask reviewer for the startup line. func reviewerState(cfg Config) string { switch { diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index f1d21b02d7..7d70f938ff 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -77,6 +77,14 @@ func TestTokenTableResolvesExactPairs(t *testing.T) { if got := builtDefaultSessionMode(t, built); got != pair.mode { t.Errorf("%s: unspecified-mode session started in %q, want %q", name, got, pair.mode) } + // The ceiling: every strict token admits all three strict modes, and no + // token admits a mode above its own allow-all tier. + for _, mode := range []session.PermissionMode{session.ModePlan, session.ModeDefault, session.ModeAccept, session.ModeYolo} { + _, err := built.Service.CreateSession(context.Background(), mode, defaultLimits()) + if wantOK := mode != session.ModeYolo || pair.posture == PostureYolo; (err == nil) != wantOK { + t.Errorf("%s: CreateSession(%s) err = %v, want admitted=%v", name, mode, err, wantOK) + } + } built.Close() } diff --git a/internal/app/posture_build_test.go b/internal/app/posture_build_test.go index e378bff6cd..1ae1a72d7c 100644 --- a/internal/app/posture_build_test.go +++ b/internal/app/posture_build_test.go @@ -290,3 +290,43 @@ func (r *slogdiagRecorder) lineContaining(substr string) string { } return "" } + +// TestBuildEchoesProjectTrust pins that the capabilities echo carries the +// effective project-trust decision as its own axis: an explicit trust grant +// reports trusted at strict posture, a headless allow-all root without a trust +// source reports untrusted, and the echo is always set by a composed server. +func TestBuildEchoesProjectTrust(t *testing.T) { + cases := []struct { + name string + token string + trust bool + want bool + }{ + {"default untrusted", "default", false, false}, + {"default with --trust-project", "default", true, true}, + {"headless yolo without a trust source", "yolo", false, false}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if tc.token == "yolo" { + t.Setenv("MECATL_SANDBOX", "1") + } + cfg := permissionModeCfg(t, tc.token, port.NopDiagnostics{}) + cfg.TrustProject = tc.trust + cfg.Headless = true + cfg.GuardrailsDisabled = tc.token == "yolo" + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + caps := built.Service.CompatibilityInfo(context.Background()).GetCapabilities() + if caps.ProjectTrusted == nil { + t.Fatal("project_trusted must be set by a composed server") + } + if got := caps.GetProjectTrusted(); got != tc.want { + t.Fatalf("project_trusted = %v, want %v", got, tc.want) + } + }) + } +} diff --git a/internal/app/slots.go b/internal/app/slots.go index 9fa96b2f9c..c9284a0d73 100644 --- a/internal/app/slots.go +++ b/internal/app/slots.go @@ -841,19 +841,31 @@ func boundedRouterFact(value string) string { // keep the session model). The predicate intentionally compares against cfg.Model (the // shared-engine model), because promotion only matters for a session that would // otherwise ride the shared engine. +// +// It is also true for a mode whose guardrail enforcement differs from the shared +// engine's: the shared engine demotes the checker to advisory only at yolo +// posture, so on a yolo server a non-yolo session (notably auto, which requires +// an enforcing checker) is promoted to a per-session engine compiled for its own +// mode (guardrailsDemoted). func modeNeedsEngine(cfg Config) func(mode session.PermissionMode) bool { providerID := strings.TrimSpace(cfg.DefaultProvider) if cfg.modelProviderRegistry != nil { providerID = cfg.modelProviderRegistry.Default() } planModel, crossProviderFallback := resolvePlanSessionModel(cfg, providerID, cfg.Model, session.ModePlan) - if !crossProviderFallback && planModel == cfg.Model { - // No active plan slot (or it resolves to the shared-engine model): a mode flip - // never changes the model, so never promote — nil keeps the default-FS path - // byte-identical. + planPromotes := crossProviderFallback || planModel != cfg.Model + guardrailsPromote := guardrailsConfigured(cfg) + if !planPromotes && !guardrailsPromote { + // No active plan slot (or it resolves to the shared-engine model) and no + // checker: a mode flip never changes the engine, so never promote — nil + // keeps the default-FS path byte-identical. return nil } + sharedDemoted := guardrailsDemoted(cfg) return func(mode session.PermissionMode) bool { - return mode == session.ModePlan + if planPromotes && mode == session.ModePlan { + return true + } + return guardrailsPromote && (mode == session.ModeYolo) != sharedDemoted } } diff --git a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts index 0ff52f0350..f2e85bc138 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("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIpgDChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSMAoJZXhlY3V0aW9uGAwgASgLMh0ubWVjYXRsLnYxLkV4ZWN1dGlvblNlbGVjdGlvbhIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMSHQoVYWdlbnRfZGVmaW5pdGlvbl9uYW1lGA0gASgJSgQIARACSgQICBAJSgQIBhAHUgl3b3Jrc3BhY2VSEXNvdXJjZV9zZXNzaW9uX2lkUgdwcm9maWxlImwKEkV4ZWN1dGlvblNlbGVjdGlvbhImCgRub25lGAEgASgLMhgubWVjYXRsLnYxLkV4ZWN1dGlvbk5vbmUSLgoIdGVtcGxhdGUYAiABKAsyHC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGUiDwoNRXhlY3V0aW9uTm9uZSIxChFFeGVjdXRpb25UZW1wbGF0ZRIKCgJpZBgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCSIfCh1MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdCJtCh5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USLwoFaXRlbXMYASADKAsyIC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGVJbmZvEhoKEmludmVudG9yeV9yZXZpc2lvbhgCIAEoCSK9AgoVRXhlY3V0aW9uVGVtcGxhdGVJbmZvEi4KCHRlbXBsYXRlGAEgASgLMhwubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSFQoNZGlzcGxheV90b2tlbhgEIAEoCRJECgpleHRlbnNpb25zGAUgAygLMjAubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlSW5mby5FeHRlbnNpb25zRW50cnkSIAoYZGVjbGFyZWRfZXhlY3V0aW9uX2ZpbGVzGAYgASgIEh8KF2RlY2xhcmVkX2J1aWx0X2luX3NoZWxsGAcgASgIGjEKD0V4dGVuc2lvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIrEBCg1NY3BTZXJ2ZXJTcGVjEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEgwKBHR5cGUYAyABKAkSDwoHY29tbWFuZBgEIAEoCRI2CgdoZWFkZXJzGAUgAygLMiUubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMuSGVhZGVyc0VudHJ5Gi4KDEhlYWRlcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIisKFEdldFNlcnZlckluZm9SZXF1ZXN0EhMKC3Byb3ZpZGVyX2lkGAEgASgJIm8KFUdldFNlcnZlckluZm9SZXNwb25zZRIQCghidWlsZF9pZBgBIAEoCRIdChVzZXJ2ZXJfaW1wbGVtZW50YXRpb24YAiABKAkSJQodbGxtX3Byb3ZpZGVyX2Rpc3BsYXlfZW5kcG9pbnQYAyABKAkiHQobR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0IowBChxHZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEhEKCWFwaV9tYWpvchgBIAEoBRIzCgxjYXBhYmlsaXRpZXMYAiABKAsyHS5tZWNhdGwudjEuU2VydmVyQ2FwYWJpbGl0aWVzEhAKCGZlYXR1cmVzGAMgAygJEhIKCmRlcGxveW1lbnQYBCABKAkivQUKElNlcnZlckNhcGFiaWxpdGllcxILCgNtY3AYASABKAgSFgoOc2xhc2hfY29tbWFuZHMYAiABKAgSDgoGbWVtb3J5GAMgASgIEg4KBnNraWxscxgEIAEoCBINCgV0ZWFtcxgFIAEoCBINCgVzaGVsbBgGIAEoCBINCgVpbWFnZRgHIAEoCBINCgVhdWRpbxgIIAEoCBIOCgZhZ2VudHMYCSABKAgSDAoEc291bBgKIAEoCBISCgp1c2VyX21vZGVsGAsgASgIEhcKD21vZGVsX3NlbGVjdGlvbhgMIAEoCBIPCgdwb3N0dXJlGA0gASgJEhEKCXdvcmt0cmVlcxgOIAEoCBISCgpzY2hlZHVsaW5nGA8gASgIEhIKCnJlZmxlY3Rpb24YECABKAgSGgoSbGVhcm5pbmdfcHJvcG9zYWxzGBEgASgIEhYKDmxlYXJuZWRfc2tpbGxzGBIgASgIEhcKD3N0b3JhZ2VfY2xlYW51cBgWIAEoCBI4CgxtYW51YWxfZHJlYW0YEyABKAsyIi5tZWNhdGwudjEuTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSFgoOc3RvcmFnZV9oZWFsdGgYFyABKAgSDQoFc3RlZXIYGCABKAgSGQoRbWFudWFsX2NvbXBhY3Rpb24YGSABKAgSFQoNc2Vzc2lvbl9kZWJ1ZxgaIAEoCBIRCglkZWJ1Z19tY3AYGyABKAgSHAoUd29ya3NwYWNlX2Vucm9sbG1lbnQYHCABKAgSHAoUbWNwX2Nvbm5lY3Rvcl9zdGF0dXMYHSABKAgSEwoLbWNwX3JlZnJlc2gYHiABKAgSGwoTZXhlY3V0aW9uX3RlbXBsYXRlcxgfIAEoCEoECBQQFUoECBUQFlIPbGVnYWN5X2Fkb3B0aW9uUhFzdG9yYWdlX21pZ3JhdGlvbiI1Ch9MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkisgEKIExpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1Jlc3BvbnNlEhQKDGF2YWlsYWJpbGl0eRgBIAEoCRIYChBlbnJvbGxtZW50X3N0YXRlGAIgASgJEjEKCmNvbm5lY3RvcnMYAyADKAsyHS5tZWNhdGwudjEuTWNwQ29ubmVjdG9yU3RhdHVzEhgKEHRvdGFsX2Nvbm5lY3RvcnMYBCABKA0SEQoJdHJ1bmNhdGVkGAUgASgIIk8KEk1jcENvbm5lY3RvclN0YXR1cxIMCgRuYW1lGAEgASgJEhcKD2NhdGFsb2d1ZV9zdGF0ZRgCIAEoCRISCgp0b29sX2NvdW50GAMgASgNIogCChVDcmVhdGVTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgDIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEjAKDnJlc29sdmVkX21vZGVsGAQgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSLwoJcGxhY2VtZW50GAUgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEiYKHnJlc29sdmVkX2FnZW50X2RlZmluaXRpb25fbmFtZRgGIAEoCUoECAIQA1IMY2FwYWJpbGl0aWVzIlIKEVBsYWNlbWVudE1ldGFkYXRhEgwKBGtpbmQYASABKAkSDQoFbGFiZWwYAiABKAkSDgoGYnJhbmNoGAMgASgJEhAKCHJldmlzaW9uGAQgASgJImgKDVJlc29sdmVkTW9kZWwSEwoLcHJvdmlkZXJfaWQYASABKAkSEAoIbW9kZWxfaWQYAiABKAkSFgoOY29udGV4dF93aW5kb3cYAyABKAMSGAoQcmVhc29uaW5nX2VmZm9ydBgEIAEoCSJkChNTZXNzaW9uQ2FwYWJpbGl0aWVzEg0KBWltYWdlGAEgASgIEg0KBWF1ZGlvGAIgASgIEhcKD2V4ZWN1dGlvbl9maWxlcxgDIAEoCBIWCg5idWlsdF9pbl9zaGVsbBgEIAEoCCIwChFHZXRTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjkKEkdldFNlc3Npb25SZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iOgobR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiUgoUQWN0aXZpdHlSZXBsYXlTdGF0dXMSEQoJYXZhaWxhYmxlGAEgASgIEhAKCGNvbXBsZXRlGAIgASgIEhUKDWF1dGhvcml0YXRpdmUYAyABKAgi7QEKHEdldFNlc3Npb25UcmFuc2NyaXB0UmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIwCghtZXNzYWdlcxgCIAMoCzIeLm1lY2F0bC52MS5Db252ZXJzYXRpb25NZXNzYWdlEhAKCGNvbXBsZXRlGAMgASgIEjEKCGFjdGl2aXR5GAQgASgLMh8ubWVjYXRsLnYxLkFjdGl2aXR5UmVwbGF5U3RhdHVzEgwKBGtpbmQYBSABKAkSNAoMcmVsYXRpb25zaGlwGAYgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXAiOQoaU3RyZWFtU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI3ChhTdHJlYW1TZXNzaW9uTGl2ZVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJYChlXYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDgoGY3Vyc29yGAIgASgJEg4KBnJ1bl9pZBgDIAEoCSJcChpXYXRjaFNlc3Npb25FdmVudHNSZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudBIOCgZjdXJzb3IYAiABKAkSDQoFcGhhc2UYAyABKAkiOAoTTGlzdFNlc3Npb25zUmVxdWVzdBIRCglwYWdlX3NpemUYASABKAUSDgoGY3Vyc29yGAIgASgJIk4KCVByaW5jaXBhbBIOCgZpc3N1ZXIYASABKAkSDwoHc3ViamVjdBgCIAEoCRISCgpncmFudF90eXBlGAMgASgJEgwKBG5hbWUYBCABKAki/gQKDlNlc3Npb25TdW1tYXJ5EhIKCnNlc3Npb25faWQYASABKAkSGAoQbW9kaWZpZWRfYXRfdW5peBgCIAEoAxINCgVzdGF0ZRgDIAEoCRINCgV0dXJucxgEIAEoBRIQCghtb2RlbF9pZBgFIAEoCRIXCg9jcmVhdGVkX2F0X3VuaXgYBiABKAMSIwoFb3duZXIYCCABKAsyFC5tZWNhdGwudjEuUHJpbmNpcGFsEgwKBGtpbmQYCSABKAkSNAoMcmVsYXRpb25zaGlwGAogASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXASPQoMY2FwYWJpbGl0aWVzGAsgASgLMicubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcmVhc29uX2NvZGUYDCABKAkSLwoJcGxhY2VtZW50GA8gASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBAgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI+Cgt0b2tlbl91c2FnZRgRIAMoCzIpLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeS5Ub2tlblVzYWdlRW50cnkSFgoOYWN0aXZpdHlfc3RhdGUYEiABKAkaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECAcQCEoECA0QDkoECA4QD1IFdGl0bGVSCXdvcmtzcGFjZVIQdGl0bGVfcHJvdmVuYW5jZSLmAQoTU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFwYXJlbnRfc2Vzc2lvbl9pZBgBIAEoCRIPCgdjYWxsX2lkGAIgASgJEhkKDGJyYW5jaF9pbmRleBgDIAEoBUgAiAEBEhUKDXNjaGVkdWxlX25hbWUYBCABKAkSGQoRb3JpZ2luX3Nlc3Npb25faWQYBSABKAkSDwoHdGVhbV9pZBgGIAEoCRITCgttZW1iZXJfbmFtZRgHIAEoCRIfChdkZWJ1Z190YXJnZXRfc2Vzc2lvbl9pZBgIIAEoCUIPCg1fYnJhbmNoX2luZGV4IpICChxTZXNzaW9uSW52ZW50b3J5Q2FwYWJpbGl0aWVzEhMKC3B1YmxpY19jaGF0GAEgASgIEg8KB2luc3BlY3QYAiABKAgSIAoYYXV0aG9yaXRhdGl2ZV90cmFuc2NyaXB0GAMgASgIEhcKD2FjdGl2aXR5X3JlcGxheRgEIAEoCBIPCgdjb3B5X2lkGAUgASgIEhcKD3ZpZXdfdHJhbnNjcmlwdBgGIAEoCBIMCgRmb3JrGAcgASgIEg4KBnJlbmFtZRgIIAEoCBIOCgZkZWxldGUYCSABKAgSOQoHcmVhc29ucxgKIAEoCzIoLm1lY2F0bC52MS5TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucyKdAQodU2Vzc2lvbkludmVudG9yeUFjdGlvblJlYXNvbnMSEwoLcHVibGljX2NoYXQYASABKAkSDwoHaW5zcGVjdBgCIAEoCRIPCgdjb3B5X2lkGAMgASgJEhcKD3ZpZXdfdHJhbnNjcmlwdBgEIAEoCRIMCgRmb3JrGAUgASgJEg4KBnJlbmFtZRgGIAEoCRIOCgZkZWxldGUYByABKAkibQoUTGlzdFNlc3Npb25zUmVzcG9uc2USKwoIc2Vzc2lvbnMYASADKAsyGS5tZWNhdGwudjEuU2Vzc2lvblN1bW1hcnkSEwoLbmV4dF9jdXJzb3IYAiABKAkSEwoLdG90YWxfY291bnQYAyABKAUiGQoXR2V0U3RvcmFnZUhlYWx0aFJlcXVlc3Qi3gEKD1JldGVudGlvblBvbGljeRIcChRtYWluX21heF9hZ2Vfc2Vjb25kcxgBIAEoAxIWCg5tYWluX21heF9jb3VudBgCIAEoBRIdChVjaGlsZF9tYXhfYWdlX3NlY29uZHMYAyABKAMSFwoPY2hpbGRfbWF4X2NvdW50GAQgASgFEiEKGXNjaGVkdWxlZF9tYXhfYWdlX3NlY29uZHMYBSABKAMSGwoTc2NoZWR1bGVkX21heF9jb3VudBgGIAEoBRIdChVzd2VlcF9jYWRlbmNlX3NlY29uZHMYByABKAMiyQcKGEdldFN0b3JhZ2VIZWFsdGhSZXNwb25zZRIRCglhdmFpbGFibGUYASABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAIgASgJEhUKDWN1cnJlbnRfYnl0ZXMYAyABKAMSHwoXY3VycmVudF9ieXRlc19hdmFpbGFibGUYBCABKAgSGQoRcmVjbGFpbWFibGVfYnl0ZXMYBSABKAMSIwobcmVjbGFpbWFibGVfYnl0ZXNfYXZhaWxhYmxlGAYgASgIEhUKDXNlc3Npb25fY291bnQYByABKAMSEgoKZmlsZV9jb3VudBgIIAEoAxIQCgh2MV9jb3VudBgJIAEoAxIQCgh2Ml9jb3VudBgKIAEoAxISCgptYWluX2NvdW50GAsgASgDEhMKC2NoaWxkX2NvdW50GAwgASgDEhcKD3NjaGVkdWxlZF9jb3VudBgNIAEoAxIVCg11bmtub3duX2NvdW50GA4gASgDEhUKDWNvcnJ1cHRfY291bnQYDyABKAMSKgoGcG9saWN5GBAgASgLMhoubWVjYXRsLnYxLlJldGVudGlvblBvbGljeRIXCg9sYXN0X3N3ZWVwX3VuaXgYESABKAMSHAoUbGFzdF9zd2VlcF9hdmFpbGFibGUYEiABKAgSFwoPbmV4dF9zd2VlcF91bml4GBMgASgDEhwKFG5leHRfc3dlZXBfYXZhaWxhYmxlGBQgASgIEhIKCmFjdGl2ZV9qb2IYFSABKAkSFAoMbGFzdF9mYWlsdXJlGBYgASgJEiQKHG93bmVybGVzc19zZXNzaW9uc19hdmFpbGFibGUYFyABKAgSLQolb3duZXJsZXNzX3Nlc3Npb25zX3VuYXZhaWxhYmxlX3JlYXNvbhgYIAEoCRIfChdvd25lcmxlc3Nfc2Vzc2lvbl9jb3VudBgZIAEoAxIdChVvd25lcmxlc3Nfc2Vzc2lvbl9pZHMYGiADKAkSJwofb3duZXJsZXNzX3Nlc3Npb25faWRzX3RydW5jYXRlZBgbIAEoCBIlCh1vd25lcmxlc3Nfc2NoZWR1bGVzX2F2YWlsYWJsZRgcIAEoCBIuCiZvd25lcmxlc3Nfc2NoZWR1bGVzX3VuYXZhaWxhYmxlX3JlYXNvbhgdIAEoCRIgChhvd25lcmxlc3Nfc2NoZWR1bGVfY291bnQYHiABKAMSIAoYb3duZXJsZXNzX3NjaGVkdWxlX25hbWVzGB8gAygJEioKIm93bmVybGVzc19zY2hlZHVsZV9uYW1lc190cnVuY2F0ZWQYICABKAgi2QIKDUNsZWFudXBDb3VudHMSDQoFdG90YWwYASABKAUSNQoHYnlfa2luZBgCIAMoCzIkLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5S2luZEVudHJ5EjcKCGJ5X3N0YXRlGAMgAygLMiUubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlTdGF0ZUVudHJ5EjkKCWJ5X3JlYXNvbhgEIAMoCzImLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5UmVhc29uRW50cnkaLQoLQnlLaW5kRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARouCgxCeVN0YXRlRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARovCg1CeVJlYXNvbkVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEihgEKEENsZWFudXBDYW5kaWRhdGUSEgoKc2Vzc2lvbl9pZBgBIAEoCRIMCgRraW5kGAIgASgJEg0KBXN0YXRlGAMgASgJEg4KBnJlYXNvbhgEIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAUgASgDEhcKD2VzdGltYXRlZF9ieXRlcxgGIAEoAyIqChlQbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0Eg0KBWtpbmRzGAEgAygJItMCChpQbGFuU2Vzc2lvbkNsZWFudXBSZXNwb25zZRIaChJjb25maXJtYXRpb25fdG9rZW4YASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRISCgpnZW5lcmF0aW9uGAQgASgJEhYKDnBvbGljeV92ZXJzaW9uGAUgASgJEi0KCGVsaWdpYmxlGAYgAygLMhsubWVjYXRsLnYxLkNsZWFudXBDYW5kaWRhdGUSKwoJcHJvdGVjdGVkGAcgASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMSFwoPZXN0aW1hdGVkX2J5dGVzGAggASgDEhYKDnBsYW5uZWRfam9iX2lkGAkgASgJEjEKD2VsaWdpYmxlX2NvdW50cxgKIAEoCzIYLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzIkEKGkFwcGx5U2Vzc2lvbkNsZWFudXBSZXF1ZXN0EiMKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCUIHukgEcgIQASI2ChtDYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjYKG0dldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiTQoQQ2xlYW51cEl0ZW1FcnJvchITCgtpdGVtX2hhbmRsZRgBIAEoCRITCgtyZWFzb25fY29kZRgCIAEoCRIPCgdtZXNzYWdlGAMgASgJIqwBCgpDbGVhbnVwSm9iEg4KBmpvYl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIRCglwcm9jZXNzZWQYAyABKAUSDwoHZGVsZXRlZBgEIAEoBRIPCgdza2lwcGVkGAUgASgFEg0KBXN0YWxlGAYgASgFEg4KBmZhaWxlZBgHIAEoBRIrCgZlcnJvcnMYCCADKAsyGy5tZWNhdGwudjEuQ2xlYW51cEl0ZW1FcnJvciJWCg5TZXRNb2RlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEicKBG1vZGUYAiABKA4yGS5tZWNhdGwudjEuUGVybWlzc2lvbk1vZGUiNgoPU2V0TW9kZVJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiIyChNDbG9zZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiFgoUQ2xvc2VTZXNzaW9uUmVzcG9uc2UiSwoUUmVuYW1lU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIWCgV0aXRsZRgCIAEoCUIHukgEcgIQASI8ChVSZW5hbWVTZXNzaW9uUmVzcG9uc2USIwoHc2Vzc2lvbhgBIAEoCzISLm1lY2F0bC52MS5TZXNzaW9uIjMKFERlbGV0ZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiFwoVRGVsZXRlU2Vzc2lvblJlc3BvbnNlIm8KE0NsZWFyU2Vzc2lvblJlcXVlc3QSIgoRc291cmNlX3Nlc3Npb25faWQYASABKAlCB7pIBHICEAESHgoRd29ya3RyZWVfc2VsZWN0b3IYAiABKAlIAIgBAUIUChJfd29ya3RyZWVfc2VsZWN0b3IiWwoUQ2xlYXJTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIvCglwbGFjZW1lbnQYAiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGEivgEKEkZvcmtTZXNzaW9uUmVxdWVzdBIiChFzb3VyY2Vfc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARINCgV0aXRsZRgCIAEoCRIYChByZWFzb25pbmdfZWZmb3J0GAMgASgJEh4KEXdvcmt0cmVlX3NlbGVjdG9yGAQgASgJSACIAQESEwoLcHJvdmlkZXJfaWQYBSABKAkSEAoIbW9kZWxfaWQYBiABKAlCFAoSX3dvcmt0cmVlX3NlbGVjdG9yIloKE0ZvcmtTZXNzaW9uUmVzcG9uc2USEgoKc2Vzc2lvbl9pZBgBIAEoCRIvCglwbGFjZW1lbnQYAiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGEiOwoQQ29udGV4dE9jY3VwYW5jeRIUCgxpbnB1dF90b2tlbnMYASABKAMSEQoJZXN0aW1hdGVkGAIgASgIIqwGCgdTZXNzaW9uEhIKCnNlc3Npb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkSJwoEbW9kZRgDIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIhCgZsaW1pdHMYBSABKAsyES5tZWNhdGwudjEuTGltaXRzEg0KBXR1cm5zGAYgASgFEhIKCnRvb2xfY2FsbHMYByABKAUSFwoPY3JlYXRlZF9hdF91bml4GAggASgDEjAKDnJlc29sdmVkX21vZGVsGAkgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSDAoEa2luZBgOIAEoCRI0CgxyZWxhdGlvbnNoaXAYDyABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFkZWJ1Z19tY3Bfc2VydmVycxgQIAMoCRIXCg9kZWJ1Z19tY3BfdG9vbHMYESADKAkSLwoJcGxhY2VtZW50GBIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBMgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI3Cgt0b2tlbl91c2FnZRgUIAMoCzIiLm1lY2F0bC52MS5TZXNzaW9uLlRva2VuVXNhZ2VFbnRyeRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgVIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEj0KGGxhdGVzdF9jb250ZXh0X29jY3VwYW5jeRgWIAEoCzIbLm1lY2F0bC52MS5Db250ZXh0T2NjdXBhbmN5GkgKD1Rva2VuVXNhZ2VFbnRyeRILCgNrZXkYASABKAkSJAoFdmFsdWUYAiABKAsyFS5tZWNhdGwudjEuVG9rZW5Vc2FnZToCOAFKBAgEEAVKBAgKEAtKBAgLEAxKBAgMEA1KBAgNEA5SCXdvcmtzcGFjZVIFdGl0bGVSDGNhcGFiaWxpdGllc1IQdGl0bGVfcHJvdmVuYW5jZVIaYWRvcHRpb25fc291cmNlX3Nlc3Npb25faWQilQEKDFNlc3Npb25UaXRsZRINCgV0aXRsZRgBIAEoCRISCgpwcm92ZW5hbmNlGAIgASgJEhgKEGdlbmVyYXRpb25fc3RhdGUYAyABKAkSNgoObGF0ZXN0X2F0dGVtcHQYBCABKAsyHi5tZWNhdGwudjEuVGl0bGVBdHRlbXB0U3VtbWFyeRIQCghyZXZpc2lvbhgFIAEoBCI4ChNUaXRsZUF0dGVtcHRTdW1tYXJ5EgoKAmlkGAEgASgJEg8KB291dGNvbWUYAiABKAlKBAgDEAQioQEKClRva2VuVXNhZ2USHwoFdG90YWwYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USMQoGbW9kZWxzGAIgAygLMiEubWVjYXRsLnYxLlRva2VuVXNhZ2UuTW9kZWxzRW50cnkaPwoLTW9kZWxzRW50cnkSCwoDa2V5GAEgASgJEh8KBXZhbHVlGAIgASgLMhAubWVjYXRsLnYxLlVzYWdlOgI4ASLEAgoPQ29udmVyc2VSZXF1ZXN0EiMKBnByb21wdBgBIAEoCzIRLm1lY2F0bC52MS5Qcm9tcHRIABImCgVyZXRyeRgCIAEoCzIVLm1lY2F0bC52MS5SZXRyeVN0YXJ0SAASNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAEi4KDGNhbmNlbF9jaGlsZBgMIAEoCzIWLm1lY2F0bC52MS5DYW5jZWxDaGlsZEgAEiEKBXN0ZWVyGA0gASgLMhAubWVjYXRsLnYxLlN0ZWVySAASLgoMc3RlZXJfY2FuY2VsGA4gASgLMhYubWVjYXRsLnYxLlN0ZWVyQ2FuY2VsSABCBgoEa2luZCIzChBDb252ZXJzZVJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IpwBCgdDb250ZW50EiUKBGtpbmQYASABKA4yFy5tZWNhdGwudjEuQ29udGVudC5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCSI8CgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABIOCgpLSU5EX0lNQUdFEAESDgoKS0lORF9BVURJTxACIpADCgxDb250ZW50QmxvY2sSKgoEa2luZBgBIAEoDjIcLm1lY2F0bC52MS5Db250ZW50QmxvY2suS2luZBIRCgltaW1lX3R5cGUYAiABKAkSDAoEZGF0YRgDIAEoDBILCgN1cmwYBCABKAkSDAoEdGV4dBgFIAEoCRIMCgRuYW1lGAYgASgJEg0KBXRpdGxlGAcgASgJEhMKC2Rlc2NyaXB0aW9uGAggASgJEgwKBHNpemUYCSABKAMSEAoIYXVkaWVuY2UYCiADKAkSEAoIcHJpb3JpdHkYCyABKAESFQoNbGFzdF9tb2RpZmllZBgMIAEoCSKcAQoES2luZBIUChBLSU5EX1VOU1BFQ0lGSUVEEAASDQoJS0lORF9URVhUEAESDgoKS0lORF9JTUFHRRACEg4KCktJTkRfQVVESU8QAxIWChJLSU5EX1JFU09VUkNFX0xJTksQBBIaChZLSU5EX0VNQkVEREVEX1JFU09VUkNFEAUSGwoXS0lORF9TVFJVQ1RVUkVEX0NPTlRFTlQQBiIpCgpSZXRyeVN0YXJ0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEifgoGUHJvbXB0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEdGV4dBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50EiYKHnNlcnZlcl9vd25lZF9wbGFuX2NvbnRpbnVhdGlvbhgEIAEoCCLXAQoOUmVzdW1lQXBwcm92YWwSFwoGYXNrX2lkGAEgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYAyABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMSFwoPZXhwZWN0ZWRfcnVuX2lkGAQgASgJEhEKCXJldmlld19pZBgFIAEoCRI4Cg5ndWFyZHJhaWxfa2luZBgGIAEoDjIgLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbEtpbmRKBAgCEANSBWFsbG93IiEKBkNhbmNlbBIXCg9leHBlY3RlZF9ydW5faWQYASABKAkiKAoLQ2FuY2VsQ2hpbGQSGQoIY2hpbGRfaWQYASABKAlCB7pIBHICEAEiZQoFU3RlZXISDAoEdGV4dBgBIAEoCRISCgptZXNzYWdlX2lkGAIgASgJEiEKBXBhcnRzGAMgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSFwoPZXhwZWN0ZWRfcnVuX2lkGAQgASgJIjoKC1N0ZWVyQ2FuY2VsEhIKCm1lc3NhZ2VfaWQYASABKAkSFwoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJIvYBChRSZXNvbHZlUnVuQXNrUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIXCgZhc2tfaWQYAyABKAlCB7pIBHICEAESOQoHdmVyZGljdBgEIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAxIRCglyZXZpZXdfaWQYBSABKAkSOAoOZ3VhcmRyYWlsX2tpbmQYBiABKA4yIC5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxLaW5kIjcKFVJlc29sdmVSdW5Bc2tSZXNwb25zZRIOCgZydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIqoBChVSZXNvbHZlUGxhbkFza1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESFwoGYXNrX2lkGAMgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYBCABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMiOAoWUmVzb2x2ZVBsYW5Bc2tSZXNwb25zZRIOCgZydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIlEKEENhbmNlbFJ1blJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAEiIwoRQ2FuY2VsUnVuUmVzcG9uc2USDgoGcnVuX2lkGAEgASgJIpACCg9TdGVlclJ1blJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESDAoEdGV4dBgDIAEoCRIrCgVwYXJ0cxgEIAMoCzISLm1lY2F0bC52MS5Db250ZW50Qgi6SAWSAQIQEBIbCgptZXNzYWdlX2lkGAUgASgJQge6SARyAhhAOma6SGMaYQoRc3RlZXJfcnVuLmNvbnRlbnQSI3RleHQgYW5kIHBhcnRzIGNhbm5vdCBib3RoIGJlIGVtcHR5Gid0aGlzLnRleHQgIT0gJycgfHwgc2l6ZSh0aGlzLnBhcnRzKSA+IDAiYAoQU3RlZXJSdW5SZXNwb25zZRIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIOCgZydW5faWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCSJzChVDYW5jZWxSdW5TdGVlclJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESGwoKbWVzc2FnZV9pZBgDIAEoCUIHukgEcgIYQCJmChZDYW5jZWxSdW5TdGVlclJlc3BvbnNlEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEg4KBnJ1bl9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJImgKJkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIQoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCUIHukgEcgIQASI2CidHZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uUmVzcG9uc2USCwoDdXJsGAEgASgJIrQBCh5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkIKH1JlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQiswEKHUNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSGAoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCRI0Cg9yZXN1bWVfYXBwcm92YWwYCiABKAsyGS5tZWNhdGwudjEuUmVzdW1lQXBwcm92YWxIABIjCgZjYW5jZWwYCyABKAsyES5tZWNhdGwudjEuQ2FuY2VsSABCCQoHY29udHJvbCJBCh5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQikAEKDUF1dGhvcml6YXRpb24SGAoQYXV0aG9yaXphdGlvbl9pZBgBIAEoCRIPCgdjYWxsX2lkGAIgASgJEi4KCmV4cGlyZXNfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEg4KBnN0YXR1cxgEIAEoCRIUCgxkaXNwbGF5X25hbWUYBSABKAkiPgoXUGxhbkNvbnRpbnVhdGlvbkZhaWx1cmUSEwoLcGxhbl9ydW5faWQYASABKAkSDgoGYXNrX2lkGAIgASgJIrcHCgVFdmVudBIMCgR0eXBlGAEgASgJEgsKA3NlcRgCIAEoAxIMCgR0dXJuGAMgASgFEgwKBHRleHQYBCABKAkSJgoJdG9vbF9jYWxsGAUgASgLMhMubWVjYXRsLnYxLlRvb2xDYWxsEioKC3Rvb2xfcmVzdWx0GAYgASgLMhUubWVjYXRsLnYxLlRvb2xSZXN1bHQSJQoDYXNrGAcgASgLMhgubWVjYXRsLnYxLlBlcm1pc3Npb25Bc2sSIQoGcmVzdWx0GAggASgLMhEubWVjYXRsLnYxLlJlc3VsdBIkCgh0dXJuX2VuZBgKIAEoCzISLm1lY2F0bC52MS5UdXJuRW5kEh0KBGhvb2sYCyABKAsyDy5tZWNhdGwudjEuSG9vaxIlCghzdWJhZ2VudBgMIAEoCzITLm1lY2F0bC52MS5TdWJhZ2VudBIdCgR0ZWFtGA0gASgLMg8ubWVjYXRsLnYxLlRlYW0SJQoIcGFyYWxsZWwYDiABKAsyEy5tZWNhdGwudjEuUGFyYWxsZWwSLAoIc2NoZWR1bGUYDyABKAsyGi5tZWNhdGwudjEuU2NoZWR1bGVQYXlsb2FkEiUKCGFwcHJvdmFsGBAgASgLMhMubWVjYXRsLnYxLkFwcHJvdmFsEioKC3VzZXJfcHJvbXB0GBEgASgLMhUubWVjYXRsLnYxLlVzZXJQcm9tcHQSOAoSY29tcGFjdGlvbl9hcmNoaXZlGBIgASgLMhwubWVjYXRsLnYxLkNvbXBhY3Rpb25BcmNoaXZlEiMKBXN0ZWVyGBMgASgLMhQubWVjYXRsLnYxLlN0ZWVyRWNobxIqCg1zdGVlcl9vdXRjb21lGBQgASgLMhMubWVjYXRsLnYxLlN0ZWVyQWNrEioKC21vZGVsX3JldHJ5GBUgASgLMhUubWVjYXRsLnYxLk1vZGVsUmV0cnkSDgoGcnVuX2lkGBYgASgJEiYKBXRpdGxlGBcgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRIvCg1hdXRob3JpemF0aW9uGBggASgLMhgubWVjYXRsLnYxLkF1dGhvcml6YXRpb24SMgoPY29udHJvbF9yZWZ1c2VkGBkgASgLMhkubWVjYXRsLnYxLkNvbnRyb2xSZWZ1c2VkEkUKGXBsYW5fY29udGludWF0aW9uX2ZhaWx1cmUYGiABKAsyIi5tZWNhdGwudjEuUGxhbkNvbnRpbnVhdGlvbkZhaWx1cmVKBAgJEApSBXVzYWdlIjIKDkNvbnRyb2xSZWZ1c2VkEg4KBmFza19pZBgBIAEoCRIQCghjYXRlZ29yeRgCIAEoCSJ4CgpNb2RlbFJldHJ5EjYKEXJldHJ5X2Rpc3Bvc2l0aW9uGAEgASgOMhsubWVjYXRsLnYxLlJldHJ5RGlzcG9zaXRpb24SMgoPc3RyZWFtX3Byb2dyZXNzGAIgASgOMhkubWVjYXRsLnYxLlN0cmVhbVByb2dyZXNzIlAKCVN0ZWVyRWNobxIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudCJoCghTdGVlckFjaxIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIMCgR0ZXh0GAIgASgJEhAKCHByb21vdGVkGAMgASgIEhIKCm1lc3NhZ2VfaWQYBCABKAkiLQoMR3VhcmRyYWlsUmVmEgsKA3JlZhgBIAEoCRIQCghjYXRlZ29yeRgCIAEoCSKvAwoPR3VhcmRyYWlsUmV2aWV3EhEKCXJldmlld19pZBgBIAEoCRIkCgNqb2IYAiABKA4yFy5tZWNhdGwudjEuR3VhcmRyYWlsSm9iEjIKCmFzc2Vzc21lbnQYAyABKA4yHi5tZWNhdGwudjEuR3VhcmRyYWlsQXNzZXNzbWVudBIyCgppbnNwZWN0aW9uGAQgASgOMh4ubWVjYXRsLnYxLkd1YXJkcmFpbEluc3BlY3Rpb24SNAoLZGlzcG9zaXRpb24YBSABKA4yHy5tZWNhdGwudjEuR3VhcmRyYWlsRGlzcG9zaXRpb24SEwoLcmVhc29uX2NvZGUYBiABKAkSDwoHcnVsZV9pZBgHIAEoCRITCgtydWxlX29yaWdpbhgIIAEoCRIbChNjaGVja2VyX3Byb3ZpZGVyX2lkGAkgASgJEhgKEGNoZWNrZXJfbW9kZWxfaWQYCiABKAkSKQoIY29uY2VybnMYCyADKAsyFy5tZWNhdGwudjEuR3VhcmRyYWlsUmVmEigKB3NvdXJjZXMYDCADKAsyFy5tZWNhdGwudjEuR3VhcmRyYWlsUmVmIqcBChZHdWFyZHJhaWxBcHByb3ZhbFNjb3BlEhEKCXJldmlld19pZBgBIAEoCRIuCgRraW5kGAIgASgOMiAubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsS2luZBIUCgxncmFudF9kaWdlc3QYAyABKAkSFAoMc2Vzc2lvbl9vbmx5GAQgASgIEhgKEHJlcGVhdF9hdmFpbGFibGUYBSABKAhKBAgGEAciMgocTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJItMBChZHdWFyZHJhaWxDb3ZlcmFnZUVudHJ5EgwKBHRvb2wYASABKAkSDQoFcGhhc2UYAiABKAkSJAoDam9iGAMgASgOMhcubWVjYXRsLnYxLkd1YXJkcmFpbEpvYhIMCgRtb2RlGAQgASgJEg8KB3J1bGVfaWQYBSABKAkSEwoLcnVsZV9vcmlnaW4YBiABKAkSMgoKaW5zcGVjdGlvbhgHIAEoDjIeLm1lY2F0bC52MS5HdWFyZHJhaWxJbnNwZWN0aW9uEg4KBnJlYXNvbhgIIAEoCSKbAQodTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVzcG9uc2USDwoHZW5hYmxlZBgBIAEoCBIbChNjaGVja2VyX3Byb3ZpZGVyX2lkGAIgASgJEhgKEGNoZWNrZXJfbW9kZWxfaWQYAyABKAkSMgoHZW50cmllcxgEIAMoCzIhLm1lY2F0bC52MS5HdWFyZHJhaWxDb3ZlcmFnZUVudHJ5IkgKH0dldEd1YXJkcmFpbFJldmlld0RldGFpbFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIRCglyZXZpZXdfaWQYAiABKAkicwogR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVzcG9uc2USEQoJcmV2aWV3X2lkGAEgASgJEg8KB2NvbmNlcm4YAiABKAkSFgoOc291cmNlX2Rpc3BsYXkYAyABKAkSEwoLbmV4dF9hY3Rpb24YBCABKAkikAEKCEFwcHJvdmFsEg4KBmFza19pZBgBIAEoCRIMCgR0b29sGAMgASgJEg8KB2NhbGxfaWQYBCABKAkSKwoHdmVyZGljdBgGIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3QSDgoGb3JpZ2luGAcgASgJSgQIAhADSgQIBRAGUgxhbGxvd19hbHdheXMiUAoKVXNlclByb21wdBIMCgR0ZXh0GAEgASgJEiEKBXBhcnRzGAIgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSEQoJc3ludGhldGljGAMgASgIIkUKEUNvbXBhY3Rpb25BcmNoaXZlEjAKCHJlcGxhY2VkGAEgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2Ui7wEKE0NvbnZlcnNhdGlvbk1lc3NhZ2USDAoEcm9sZRgBIAEoCRIMCgR0ZXh0GAIgASgJEicKCnRvb2xfY2FsbHMYAyADKAsyEy5tZWNhdGwudjEuVG9vbENhbGwSKgoLdG9vbF9yZXN1bHQYBCABKAsyFS5tZWNhdGwudjEuVG9vbFJlc3VsdBIRCglyZWFzb25pbmcYBSABKAkSFgoOcHJvdmlkZXJfcGhhc2UYBiABKAkSIQoFcGFydHMYByADKAsyEi5tZWNhdGwudjEuQ29udGVudBIZChFyZWFzb25pbmdfaXRlbV9pZBgIIAEoCSJ2Cg9TY2hlZHVsZVBheWxvYWQSFQoNc2NoZWR1bGVfbmFtZRgBIAEoCRIPCgdmaXJlX2lkGAIgASgJEhIKCnNlc3Npb25faWQYAyABKAkSDAoEa2luZBgEIAEoCRIMCgRzdG9wGAUgASgJEgsKA2VychgGIAEoCSKOAQoESG9vaxINCgVwaGFzZRgBIAEoCRIMCgR0b29sGAIgASgJEikKCGRlY2lzaW9uGAMgASgOMhcubWVjYXRsLnYxLkhvb2tEZWNpc2lvbhIPCgdjYWxsX2lkGAQgASgJEi0KCWd1YXJkcmFpbBgFIAEoCzIaLm1lY2F0bC52MS5HdWFyZHJhaWxSZXZpZXciqAIKD1JvdXRpbmdEZWNpc2lvbhIPCgdiYWNrZW5kGAEgASgJEhgKEGNsYXNzaWZpZXJfbW9kZWwYAiABKAkSGgoSY2FuZGlkYXRlX2NhdGVnb3J5GAMgASgJEhcKD2NhbmRpZGF0ZV9tb2RlbBgEIAEoCRIXCgpjb25maWRlbmNlGAUgASgBSACIAQESHwoSbWluaW11bV9jb25maWRlbmNlGAYgASgBSAGIAQESDwoHb3V0Y29tZRgHIAEoCRIaChJjb25zZWN1dGl2ZV9taXNzZXMYCCABKAUSEgoKbWlzc19saW1pdBgJIAEoBRIUCgxicmVha2VyX29wZW4YCiABKAhCDQoLX2NvbmZpZGVuY2VCFQoTX21pbmltdW1fY29uZmlkZW5jZSKKBAoIU3ViYWdlbnQSFgoOcGFyZW50X2NhbGxfaWQYASABKAkSEAoIY2hpbGRfaWQYAiABKAkSDAoEZ29hbBgDIAEoCRIRCgl0b29sX25hbWUYBCABKAkSEAoIaXNfZXJyb3IYBSABKAgSEgoKdG9vbF9jb3VudBgGIAEoBRIfCgV1c2FnZRgHIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIMCgRzdG9wGAggASgJEhMKC2R1cmF0aW9uX21zGAkgASgDEhIKCmJhY2tncm91bmQYCiABKAgSFwoPcm91dGVkX2NhdGVnb3J5GAsgASgJEhQKDHJvdXRlZF9tb2RlbBgMIAEoCRINCgVtb2RlbBgNIAEoCRISCgppbm5lcl9raW5kGA4gASgJEgwKBHRleHQYDyABKAkSDgoGZGV0YWlsGBAgASgJEg0KBWNhdXNlGBEgASgJEhYKDnJvdXRpbmdfcmVhc29uGBIgASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YEyABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBQgASgJEhAKCHByb3ZpZGVyGBUgASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgWIAEoCUITChFfcm91dGluZ19kZWNpc2lvbiKmAgoOVGVhbU1lbWJlclNwZWMSDAoEbmFtZRgBIAEoCRIMCgRyb2xlGAIgASgJEhAKCG11dGF0aW5nGAMgASgIEgwKBGxlYWQYBCABKAgSFwoPcm91dGVkX2NhdGVnb3J5GAUgASgJEhQKDHJvdXRlZF9tb2RlbBgGIAEoCRINCgVtb2RlbBgHIAEoCRIWCg5yb3V0aW5nX3JlYXNvbhgIIAEoCRI5ChByb3V0aW5nX2RlY2lzaW9uGAkgASgLMhoubWVjYXRsLnYxLlJvdXRpbmdEZWNpc2lvbkgAiAEBEhAKCHByb3ZpZGVyGAogASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgLIAEoCUITChFfcm91dGluZ19kZWNpc2lvbiL6AwoEVGVhbRIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIPCgd0ZWFtX2lkGAIgASgJEikKBnJvc3RlchgDIAMoCzIZLm1lY2F0bC52MS5UZWFtTWVtYmVyU3BlYxIOCgZtZW1iZXIYBCABKAkSEgoKaW5uZXJfa2luZBgFIAEoCRIMCgR0ZXh0GAYgASgJEhEKCXRvb2xfbmFtZRgHIAEoCRIOCgZkZXRhaWwYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSDgoGcm91bmRzGAogASgFEgwKBHN0b3AYCyABKAkSHwoFdXNhZ2UYDCABKAsyEC5tZWNhdGwudjEuVXNhZ2USFAoMY29udGV4dF91c2VkGA0gASgDEhYKDmNvbnRleHRfd2luZG93GA4gASgDEiIKBXRhc2tzGA8gAygLMhMubWVjYXRsLnYxLlRlYW1UYXNrEigKCGZpbmRpbmdzGBAgAygLMhYubWVjYXRsLnYxLlRlYW1GaW5kaW5nEjYKDGRpc3Bvc2l0aW9ucxgRIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SGQoRbWVtYmVyX3Nlc3Npb25faWQYEiABKAkSDQoFY2F1c2UYEyABKAkSGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBQgASgJIo4FCghQYXJhbGxlbBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIMCgRraW5kGAIgASgJEgwKBGpvaW4YAyABKAkSFAoMYnJhbmNoX2NvdW50GAQgASgFEhQKDGJyYW5jaF9pbmRleBgFIAEoBRIUCgxicmFuY2hfbGFiZWwYBiABKAkSDAoEZ29hbBgHIAEoCRIRCgl0b29sX25hbWUYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSEgoKdG9vbF9jb3VudBgKIAEoBRIOCgZmYWlsZWQYCyABKAgSDAoEc3RvcBgNIAEoCRIfCgV1c2FnZRgOIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgPIAEoAxIOCgZ3aW5uZXIYECABKAUSEAoIY2hpbGRfaWQYEiABKAkSFwoPcm91dGVkX2NhdGVnb3J5GBMgASgJEhQKDHJvdXRlZF9tb2RlbBgUIAEoCRINCgVtb2RlbBgVIAEoCRISCgppbm5lcl9raW5kGBYgASgJEgwKBHRleHQYFyABKAkSDgoGZGV0YWlsGBggASgJEhYKDnJvdXRpbmdfcmVhc29uGBkgASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YGiABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESGgoSY2hpbGRfdG9vbF9jYWxsX2lkGBsgASgJEhAKCHByb3ZpZGVyGBwgASgJEiAKGGV4cGxpY2l0X3JvdXRlcl9jYXRlZ29yeRgdIAEoCUITChFfcm91dGluZ19kZWNpc2lvbkoECAwQDUoECBEQElIJd29ya3NwYWNlUhB3aW5uZXJfd29ya3NwYWNlIjIKCFRvb2xDYWxsEgoKAmlkGAEgASgJEgwKBG5hbWUYAiABKAkSDAoEYXJncxgDIAEoCSKFAQoKVG9vbFJlc3VsdBIPCgdjYWxsX2lkGAEgASgJEg8KB2NvbnRlbnQYAiABKAkSEAoIaXNfZXJyb3IYAyABKAgSJwoGYmxvY2tzGAQgAygLMhcubWVjYXRsLnYxLkNvbnRlbnRCbG9jaxIaChJzdHJ1Y3R1cmVkX2NvbnRlbnQYBSABKAkiowEKDVBlcm1pc3Npb25Bc2sSDgoGYXNrX2lkGAEgASgJEgwKBHRvb2wYAiABKAkSDAoEYXJncxgDIAEoCRIOCgZyZWFzb24YBCABKAkSNAoJZ3VhcmRyYWlsGAUgASgLMiEubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsU2NvcGUSFAoHY2FsbF9pZBgGIAEoCUgAiAEBQgoKCF9jYWxsX2lkIoUCCgZSZXN1bHQSDAoEc3RvcBgBIAEoCRIMCgR0ZXh0GAIgASgJEh8KBXVzYWdlGAMgASgLMhAubWVjYXRsLnYxLlVzYWdlEg0KBWVycm9yGAQgASgJEjsKEXJldHJ5X2Rpc3Bvc2l0aW9uGAYgASgOMhsubWVjYXRsLnYxLlJldHJ5RGlzcG9zaXRpb25IAIgBARI3Cg9zdHJlYW1fcHJvZ3Jlc3MYByABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3NIAYgBAUIUChJfcmV0cnlfZGlzcG9zaXRpb25CEgoQX3N0cmVhbV9wcm9ncmVzc0oECAUQBlIJcGVybWFuZW50IlIKB1R1cm5FbmQSHwoFdXNhZ2UYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USEwoLZHVyYXRpb25fbXMYAiABKAMSEQoJZXN0aW1hdGVkGAMgASgIIoUBCgVVc2FnZRIUCgxpbnB1dF90b2tlbnMYASABKAMSFQoNb3V0cHV0X3Rva2VucxgCIAEoAxIZChFjYWNoZV9yZWFkX3Rva2VucxgDIAEoAxIaChJjYWNoZV93cml0ZV90b2tlbnMYBCABKAMSGAoQcmVhc29uaW5nX3Rva2VucxgFIAEoAyKQAQoLTWNwUmVzb3VyY2USDgoGc2VydmVyGAEgASgJEgsKA3VyaRgCIAEoCRIMCgRuYW1lGAMgASgJEg0KBXRpdGxlGAQgASgJEhMKC2Rlc2NyaXB0aW9uGAUgASgJEhEKCW1pbWVfdHlwZRgGIAEoCRIMCgRzaXplGAcgASgDEhEKCXJlYWRfb25seRgIIAEoCCIpChdMaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBIOCgZzZXJ2ZXIYASABKAkiRQoYTGlzdE1jcFJlc291cmNlc1Jlc3BvbnNlEikKCXJlc291cmNlcxgBIAMoCzIWLm1lY2F0bC52MS5NY3BSZXNvdXJjZSJRChNNY3BSZXNvdXJjZUNvbnRlbnRzEgsKA3VyaRgBIAEoCRIRCgltaW1lX3R5cGUYAiABKAkSDAoEdGV4dBgDIAEoCRIMCgRibG9iGAQgASgMIkcKFlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QSFwoGc2VydmVyGAEgASgJQge6SARyAhABEhQKA3VyaRgCIAEoCUIHukgEcgIQASJLChdSZWFkTWNwUmVzb3VyY2VSZXNwb25zZRIwCghjb250ZW50cxgBIAMoCzIeLm1lY2F0bC52MS5NY3BSZXNvdXJjZUNvbnRlbnRzIlcKEU1jcFByb21wdEFyZ3VtZW50EgwKBG5hbWUYASABKAkSDQoFdGl0bGUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSEAoIcmVxdWlyZWQYBCABKAgifgoJTWNwUHJvbXB0Eg4KBnNlcnZlchgBIAEoCRIMCgRuYW1lGAIgASgJEg0KBXRpdGxlGAMgASgJEhMKC2Rlc2NyaXB0aW9uGAQgASgJEi8KCWFyZ3VtZW50cxgFIAMoCzIcLm1lY2F0bC52MS5NY3BQcm9tcHRBcmd1bWVudCInChVMaXN0TWNwUHJvbXB0c1JlcXVlc3QSDgoGc2VydmVyGAEgASgJIj8KFkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USJQoHcHJvbXB0cxgBIAMoCzIULm1lY2F0bC52MS5NY3BQcm9tcHQiuQEKE0dldE1jcFByb21wdFJlcXVlc3QSFwoGc2VydmVyGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESQAoJYXJndW1lbnRzGAMgAygLMi0ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QuQXJndW1lbnRzRW50cnkaMAoOQXJndW1lbnRzRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASIuChBNY3BQcm9tcHRNZXNzYWdlEgwKBHJvbGUYASABKAkSDAoEdGV4dBgCIAEoCSJaChRHZXRNY3BQcm9tcHRSZXNwb25zZRITCgtkZXNjcmlwdGlvbhgBIAEoCRItCghtZXNzYWdlcxgCIAMoCzIbLm1lY2F0bC52MS5NY3BQcm9tcHRNZXNzYWdlIkwKDU1jcFNlcnZlckluZm8SDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSEQoJdHJhbnNwb3J0GAMgASgJEg0KBWdyb3VwGAQgASgJIocBCglNY3BTb3VyY2USDAoEbmFtZRgBIAEoCRIMCgRraW5kGAIgASgJEg8KB2VuYWJsZWQYAyABKAgSDQoFZ3JvdXAYBCABKAkSKQoHc2VydmVycxgFIAMoCzIYLm1lY2F0bC52MS5NY3BTZXJ2ZXJJbmZvEhMKC2RpYWdub3N0aWNzGAYgAygJIhcKFUxpc3RNY3BTb3VyY2VzUmVxdWVzdCJ1ChZMaXN0TWNwU291cmNlc1Jlc3BvbnNlEiUKB3NvdXJjZXMYASADKAsyFC5tZWNhdGwudjEuTWNwU291cmNlEhAKCHJldmlzaW9uGAIgASgEEg0KBXN0YWxlGAMgASgIEhMKC3JlY29uY2lsaW5nGAQgASgIIjcKGFJlZnJlc2hNY3BTb3VyY2VzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIj4KGVJlZnJlc2hNY3BTb3VyY2VzUmVzcG9uc2USEAoIcmV2aXNpb24YASABKAQSDwoHY2hhbmdlZBgCIAEoCCIbChlMaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0IiwKGkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEg4KBmdyb3VwcxgBIAMoCSJ0CglBZ2VudEluZm8SDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVtb2RlbBgDIAEoCRINCgV0b29scxgEIAMoCRIXCg9wZXJtaXNzaW9uX21vZGUYBSABKAkSDQoFY29sb3IYBiABKAkiEwoRTGlzdEFnZW50c1JlcXVlc3QiOgoSTGlzdEFnZW50c1Jlc3BvbnNlEiQKBmFnZW50cxgBIAMoCzIULm1lY2F0bC52MS5BZ2VudEluZm8iLAoHQ29tbWFuZBIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIjIKE0xpc3RDb21tYW5kc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI8ChRMaXN0Q29tbWFuZHNSZXNwb25zZRIkCghjb21tYW5kcxgBIAMoCzISLm1lY2F0bC52MS5Db21tYW5kImkKCFdvcmt0cmVlEhAKCHNlbGVjdG9yGAEgASgJEgwKBGtpbmQYAiABKAkSDQoFbGFiZWwYAyABKAkSDgoGYnJhbmNoGAQgASgJEhAKCHJldmlzaW9uGAUgASgJEgwKBGJhcmUYBiABKAgiMwoUTGlzdFdvcmt0cmVlc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI/ChVMaXN0V29ya3RyZWVzUmVzcG9uc2USJgoJd29ya3RyZWVzGAEgAygLMhMubWVjYXRsLnYxLldvcmt0cmVlInAKCVNraWxsSW5mbxIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEhMKC2FnZW50X293bmVkGAMgASgIEhMKC293bmVyX2FnZW50GAQgASgJEhYKDmFjdGl2ZV92ZXJzaW9uGAUgASgJIhMKEUxpc3RTa2lsbHNSZXF1ZXN0IjoKEkxpc3RTa2lsbHNSZXNwb25zZRIkCgZza2lsbHMYASADKAsyFC5tZWNhdGwudjEuU2tpbGxJbmZvIkEKDVNraWxsRmlsZUluZm8SDAoEbmFtZRgBIAEoCRIMCgRzaXplGAIgASgDEhQKDGluc3RydWN0aW9ucxgDIAEoCCIuChVMaXN0U2tpbGxGaWxlc1JlcXVlc3QSFQoEbmFtZRgBIAEoCUIHukgEcgIQASJBChZMaXN0U2tpbGxGaWxlc1Jlc3BvbnNlEicKBWZpbGVzGAEgAygLMhgubWVjYXRsLnYxLlNraWxsRmlsZUluZm8iRAoUUmVhZFNraWxsRmlsZVJlcXVlc3QSFQoEbmFtZRgBIAEoCUIHukgEcgIQARIVCgRmaWxlGAIgASgJQge6SARyAhABIigKFVJlYWRTa2lsbEZpbGVSZXNwb25zZRIPCgdjb250ZW50GAEgASgJIqEBCghTb3VsSW5mbxIPCgdjb250ZW50GAEgASgJEhIKCnNpemVfYnl0ZXMYAiABKAMSDgoGc2hhMjU2GAMgASgJEg8KB3ByZXNlbnQYBCABKAgSLQoKcHJvdmVuYW5jZRgFIAEoDjIZLm1lY2F0bC52MS5Tb3VsUHJvdmVuYW5jZRIPCgd0cnVzdGVkGAYgASgIEg8KB2RyaWZ0ZWQYByABKAgiEAoOR2V0U291bFJlcXVlc3QiNAoPR2V0U291bFJlc3BvbnNlEiEKBHNvdWwYASABKAsyEy5tZWNhdGwudjEuU291bEluZm8iMgoOVXNlck1vZGVsRW50cnkSCwoDa2V5GAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIiIKE0dldFVzZXJNb2RlbFJlcXVlc3QSCwoDa2V5GAEgASgJIpYCChFVc2VyTW9kZWxSZXZpc2lvbhILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSDwoHdmVyc2lvbhgEIAEoCRIOCgZzdGF0dXMYBSABKAkSDgoGd3JpdGVyGAYgASgJEg4KBm9yaWdpbhgHIAEoCRIZChFzb3VyY2Vfc2Vzc2lvbl9pZBgIIAEoCRIaChJzb3VyY2VfcHJvcG9zYWxfaWQYCSABKAkSLgoKdXBkYXRlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBKBAgKEAtSD3NvdXJjZV9ldmVudF9pZFIRc291cmNlX21lc3NhZ2VfaWQiigEKD1VzZXJNb2RlbERldGFpbBItCgdjdXJyZW50GAEgASgLMhwubWVjYXRsLnYxLlVzZXJNb2RlbFJldmlzaW9uEi0KB2hpc3RvcnkYAiADKAsyHC5tZWNhdGwudjEuVXNlck1vZGVsUmV2aXNpb24SGQoRaGlzdG9yeV9hdmFpbGFibGUYAyABKAgikgEKFEdldFVzZXJNb2RlbFJlc3BvbnNlEioKB2VudHJpZXMYASADKAsyGS5tZWNhdGwudjEuVXNlck1vZGVsRW50cnkSEgoKc2l6ZV9ieXRlcxgCIAEoAxIOCgZzaGEyNTYYAyABKAkSKgoGZGV0YWlsGAQgASgLMhoubWVjYXRsLnYxLlVzZXJNb2RlbERldGFpbCKSAQoJTW9kZWxJbmZvEgoKAmlkGAEgASgJEhMKC3Byb3ZpZGVyX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRINCgVpbWFnZRgEIAEoCBIRCglyZWFzb25pbmcYBSABKAgSFQoNY29udGV4dF9saW1pdBgGIAEoAxIVCg1wcm9tcHRfY2FjaGVkGAcgASgIIhMKEUxpc3RNb2RlbHNSZXF1ZXN0IpsBCg5Qcm92aWRlclN0YXR1cxITCgtwcm92aWRlcl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIMCgRoaW50GAMgASgJEiMKG2RlZmF1bHRfbW9kZWxfYXV0b19zZWxlY3RlZBgEIAEoCBITCgttb2RlbF9jb3VudBgFIAEoBRIdChVhdmFpbGFibGVfbm90X2RlZmF1bHQYBiABKAgibgoSTGlzdE1vZGVsc1Jlc3BvbnNlEiQKBm1vZGVscxgBIAMoCzIULm1lY2F0bC52MS5Nb2RlbEluZm8SMgoPcHJvdmlkZXJfc3RhdHVzGAIgAygLMhkubWVjYXRsLnYxLlByb3ZpZGVyU3RhdHVzIkEKFVJlZmxlY3RTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABSgQIAhADUgVhc3luYyK5AQoRUmVmbGVjdGlvblJlY2VpcHQSFQoNcmVmbGVjdGlvbl9pZBgBIAEoCRITCgtkaXNwb3NpdGlvbhgCIAEoCRIOCgZxdWV1ZWQYAyABKAUSEQoJYWJzdGFpbmVkGAQgASgIEg4KBnN0YWdlZBgFIAEoBRIQCghwcm9tb3RlZBgGIAEoBRISCgpjb25mbGljdGVkGAcgASgFEg4KBnJlYXNvbhgIIAEoCRIPCgdtZXNzYWdlGAkgASgJIkcKFlJlZmxlY3RTZXNzaW9uUmVzcG9uc2USLQoHcmVjZWlwdBgBIAEoCzIcLm1lY2F0bC52MS5SZWZsZWN0aW9uUmVjZWlwdCLxAgoPTGVhcm5pbmdBdHRlbXB0EgoKAmlkGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSDwoHb3V0Y29tZRgEIAEoCRIUCgxmYWlsdXJlX2NvZGUYBSABKAkSGgoSYXR0ZW1wdF9nZW5lcmF0aW9uGAYgASgEEhgKEGNsYWltX2dlbmVyYXRpb24YByABKAQSNAoQY2xhaW1fZXhwaXJlc19hdBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGAoQY2hlY2twb2ludF9zdGFnZRgJIAEoCRITCgtwcm9wb3NhbF9pZBgKIAEoCRIQCghza2lsbF9pZBgLIAEoCRIuCgpjcmVhdGVkX2F0GAwgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA0gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIwChlHZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABIkkKGkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0IksKG0xpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBINCgVzdGF0ZRgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUiYQocTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRIsCghhdHRlbXB0cxgBIAMoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQSEwoLbmV4dF9jdXJzb3IYAiABKAkiVgocTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABIkwKHU11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0Il4KHExpc3RMZWFybmluZ1Byb3Bvc2Fsc1JlcXVlc3QSDgoGc3RhdHVzGAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBRIPCgdwcm9qZWN0GAQgASgJIr4BChNMZWFybmluZ0V2aWRlbmNlUmVmEhIKCnNlc3Npb25faWQYASABKAkSDwoHbG9jYXRvchgCIAEoCRIPCgdvcmRpbmFsGAMgASgFEhEKCWV2ZW50X3NlcRgEIAEoAxIUCgx0b29sX2NhbGxfaWQYBSABKAkSDgoGZGlnZXN0GAYgASgJEhEKCWF2YWlsYWJsZRgHIAEoCBIUCgxhdmFpbGFiaWxpdHkYCCABKAkSDwoHcHJldmlldxgJIAEoCSJnChBMZWFybmluZ0RlY2lzaW9uEgwKBGtpbmQYASABKAkSDQoFYWN0b3IYAiABKAkSDgoGcmVhc29uGAMgASgJEiYKAmF0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCJ5ChhMZWFybmluZ1Byb21vdGlvblJlY2VpcHQSEgoKbWVtb3J5X2tleRgBIAEoCRIXCg9wcmV2aW91c19leGlzdHMYAiABKAgSGAoQcHJldmlvdXNfdmVyc2lvbhgDIAEoCRIWCg5yZXN1bHRfdmVyc2lvbhgEIAEoCSKcBAoQTGVhcm5pbmdQcm9wb3NhbBIKCgJpZBgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEg4KBnN0YXR1cxgDIAEoCRIMCgRraW5kGAQgASgJEgsKA2tleRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtkZXNjcmlwdGlvbhgHIAEoCRINCgV0aXRsZRgIIAEoCRIMCgRib2R5GAkgASgJEjAKCGV2aWRlbmNlGAogAygLMh4ubWVjYXRsLnYxLkxlYXJuaW5nRXZpZGVuY2VSZWYSEAoIdHJpZ2dlcnMYCyADKAkSLgoJZGVjaXNpb25zGAwgAygLMhsubWVjYXRsLnYxLkxlYXJuaW5nRGVjaXNpb24SNgoJcHJvbW90aW9uGA0gASgLMiMubWVjYXRsLnYxLkxlYXJuaW5nUHJvbW90aW9uUmVjZWlwdBIuCgpjcmVhdGVkX2F0GA4gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIWCg5wcm9qZWN0X3Njb3BlZBgQIAEoCBIbChNwcm9tb3Rpb25fYXZhaWxhYmxlGBEgASgIEiQKHHByb21vdGlvbl91bmF2YWlsYWJsZV9yZWFzb24YEiABKAkSGAoQbGVhcm5lZF9za2lsbF9pZBgTIAEoCSJkCh1MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRIuCglwcm9wb3NhbHMYASADKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbBITCgtuZXh0X2N1cnNvchgCIAEoCSJCChpHZXRMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAIgASgJIkwKG0dldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsIpMBCh1EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABEhkKCGRlY2lzaW9uGAMgASgJQge6SARyAhABEg4KBnJlYXNvbhgEIAEoCRIPCgdwcm9qZWN0GAUgASgJIk8KHkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsImcKHFVuZG9MZWFybmluZ1Byb21vdGlvblJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAMgASgJIk4KHVVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwi7AMKE0xlYXJuZWRTa2lsbFZlcnNpb24SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIPCgd2ZXJzaW9uGAMgASgJEhAKCHJldmlzaW9uGAQgASgJEg0KBXN0YXRlGAUgASgJEhMKC293bmVyX2FnZW50GAYgASgJEhMKC2Rlc2NyaXB0aW9uGAcgASgJEgwKBGJvZHkYCCABKAkSEgoKc3VwZXJzZWRlcxgJIAEoCRIWCg5ldmlkZW5jZV9jb3VudBgKIAEoBRIwCghldmlkZW5jZRgLIAMoCzIeLm1lY2F0bC52MS5MZWFybmluZ0V2aWRlbmNlUmVmEi8KC2V2YWx1YXRpb25zGAwgAygLMhoubWVjYXRsLnYxLlNraWxsRXZhbHVhdGlvbhIvCghyZWNlaXB0cxgNIAMoCzIdLm1lY2F0bC52MS5Ta2lsbENoYW5nZVJlY2VpcHQSLgoKY3JlYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgilAEKD1NraWxsRXZhbHVhdGlvbhIPCgd2ZXJkaWN0GAEgASgJEhMKC2ZpeHR1cmVfaWRzGAIgAygJEhAKCGJhc2VsaW5lGAMgASgJEhEKCXRyZWF0bWVudBgEIAEoCRIOCgZyZWFzb24YBSABKAkSJgoCYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIoIDChJTa2lsbENoYW5nZVJlY2VpcHQSCgoCaWQYASABKAkSEAoIc2tpbGxfaWQYAiABKAkSDAoEbmFtZRgDIAEoCRIPCgd2ZXJzaW9uGAQgASgJEhEKCW9wZXJhdGlvbhgFIAEoCRISCgpmcm9tX3N0YXRlGAYgASgJEhAKCHRvX3N0YXRlGAcgASgJEhYKDmV2aWRlbmNlX2NvdW50GAggASgFEhoKEnNvdXJjZV9zZXNzaW9uX2lkcxgJIAMoCRIcChRzb3VyY2VfdG9vbF9jYWxsX2lkcxgKIAMoCRIPCgd2ZXJkaWN0GAsgASgJEhMKC2ZpeHR1cmVfaWRzGAwgAygJEhAKCGJhc2VsaW5lGA0gASgJEhEKCXRyZWF0bWVudBgOIAEoCRImCgJhdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgibgoYTGlzdExlYXJuZWRTa2lsbHNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFEg0KBXN0YXRlGAQgASgJEhMKC293bmVyX2FnZW50GAUgASgJIoUBChlMaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlEi4KBnNraWxscxgBIAMoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhMKC25leHRfY3Vyc29yGAIgASgJEhIKCmdlbmVyYXRpb24YAyABKAQSDwoHcHJvamVjdBgEIAEoCSJtChZHZXRMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESDwoHdmVyc2lvbhgEIAEoCSJtChdHZXRMZWFybmVkU2tpbGxSZXNwb25zZRItCgVza2lsbBgBIAEoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCSKhAQofRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEh0KDGZyb21fdmVyc2lvbhgEIAEoCUIHukgEcgIQARIbCgp0b192ZXJzaW9uGAUgASgJQge6SARyAhABIpEBCiBEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRIMCgRkaWZmGAEgASgJEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCRIQCghza2lsbF9pZBgEIAEoCRIUCgxmcm9tX3ZlcnNpb24YBSABKAkSEgoKdG9fdmVyc2lvbhgGIAEoCSKdAQoZTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEhgKB3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEipwEKGk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEi0KBXNraWxsGAEgASgLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJEhoKEnB1YmxpY2F0aW9uX3N0YXR1cxgEIAEoCRIZChFwdWJsaWNhdGlvbl9lcnJvchgFIAEoCSKmAQobUm9sbGJhY2tMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESHwoOdGFyZ2V0X3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEiSQoXTGlzdFNraWxsQ2hhbmdlc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUihAEKGExpc3RTa2lsbENoYW5nZXNSZXNwb25zZRIuCgdjaGFuZ2VzGAEgAygLMh0ubWVjYXRsLnYxLlNraWxsQ2hhbmdlUmVjZWlwdBITCgtuZXh0X2N1cnNvchgCIAEoCRISCgpnZW5lcmF0aW9uGAMgASgEEg8KB3Byb2plY3QYBCABKAkijwEKEUNyZWF0ZVRlYW1SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEbmFtZRgCIAEoCRIoCgdtZW1iZXJzGAMgAygLMhcubWVjYXRsLnYxLlRlYW1tYXRlU3BlYxIMCgRnb2FsGAQgASgJEhcKD21heF90ZWFtX3Rva2VucxgFIAEoBSJNChJDcmVhdGVUZWFtUmVzcG9uc2USDwoHdGVhbV9pZBgBIAEoCRImCgdtZW1iZXJzGAIgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXIicQoMVGVhbW1hdGVTcGVjEhUKBG5hbWUYASABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgCIAEoCRIMCgRsZWFkGAMgASgIEhAKCG11dGF0aW5nGAQgASgIEhYKDmluaXRpYWxfcHJvbXB0GAUgASgJIpMBChRTcGF3blRlYW1tYXRlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgDIAEoCRIMCgRsZWFkGAQgASgIEhAKCG11dGF0aW5nGAUgASgIEhYKDmluaXRpYWxfcHJvbXB0GAYgASgJIj4KFVNwYXduVGVhbW1hdGVSZXNwb25zZRIlCgZtZW1iZXIYASABKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlciJwChpTZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhMKAnRvGAIgASgJQge6SARyAhABEgwKBGZyb20YAyABKAkSFQoEYm9keRgEIAEoCUIHukgEcgIQASIdChtTZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2UiSgoVQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESFwoGbWVtYmVyGAIgASgJQge6SARyAhABIhgKFkNhbmNlbFRlYW1tYXRlUmVzcG9uc2UiKgoOUnVuVGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASJlCglUZWFtRXZlbnQSDgoGbWVtYmVyGAEgASgJEh8KBWV2ZW50GAIgASgLMhAubWVjYXRsLnYxLkV2ZW50EicKB291dGNvbWUYAyABKAsyFi5tZWNhdGwudjEuVGVhbU91dGNvbWUi2wEKC1RlYW1PdXRjb21lEg4KBnJvdW5kcxgBIAEoBRIRCglxdWllc2NlbnQYAiABKAgSGAoQYnVkZ2V0X2V4aGF1c3RlZBgDIAEoCBIMCgRzdG9wGAQgASgJEh8KBXVzYWdlGAUgASgLMhAubWVjYXRsLnYxLlVzYWdlEjYKDGRpc3Bvc2l0aW9ucxgGIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SKAoIZmluZGluZ3MYByADKAsyFi5tZWNhdGwudjEuVGVhbUZpbmRpbmciKwoPTGlzdFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEicQoQTGlzdFRlYW1SZXNwb25zZRImCgdtZW1iZXJzGAEgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXISIgoFdGFza3MYAiADKAsyEy5tZWNhdGwudjEuVGVhbVRhc2sSEQoJcXVpZXNjZW50GAMgASgIIlEKClRlYW1NZW1iZXISDAoEbmFtZRgBIAEoCRISCgphZ2VudF90eXBlGAIgASgJEg0KBXN0YXRlGAMgASgJEhIKCnNlc3Npb25faWQYBCABKAkiWgoIVGVhbVRhc2sSCgoCaWQYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSEAoIYXNzaWduZWUYBCABKAkSDAoEZGVwcxgFIAMoCSIrCgtUZWFtRmluZGluZxIOCgZtZW1iZXIYASABKAkSDAoEYm9keRgCIAEoCSJ9ChVUZWFtTWVtYmVyRGlzcG9zaXRpb24SDAoEbmFtZRgBIAEoCRIPCgdzdG9wcGVkGAIgASgIEi8KBnJlYXNvbhgDIAEoDjIfLm1lY2F0bC52MS5UZWFtTWVtYmVyU3RvcFJlYXNvbhIUCgxlcnJvcl9yb3VuZHMYBCABKAUiLgoSQ2xlYW51cFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEiFQoTQ2xlYW51cFRlYW1SZXNwb25zZSJvChJBcHByb3ZlUGxhblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIuCgt0YXJnZXRfbW9kZRgCIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIMCgRub3RlGAMgASgJIokBChdNYW51YWxEcmVhbUNhcGFiaWxpdGllcxI4Cg5wcm9qZWN0X21lbW9yeRgBIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkSNAoKdXNlcl9tb2RlbBgCIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkiVQoVRHJlYW1UYXJnZXRDYXBhYmlsaXR5EhAKCGdlbmVyYXRlGAEgASgIEg4KBmRlY2lkZRgCIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAyABKAkiKgoYR2VuZXJhdGVEcmVhbVBsYW5SZXF1ZXN0Eg4KBnRhcmdldBgBIAEoCSJFChlHZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlEigKBHBsYW4YASABKAsyGi5tZWNhdGwudjEuRHJlYW1SZXZpZXdQbGFuIjsKFkRlY2lkZURyZWFtUGxhblJlcXVlc3QSDwoHcGxhbl9pZBgBIAEoCRIQCghkZWNpc2lvbhgCIAEoCSJDChdEZWNpZGVEcmVhbVBsYW5SZXNwb25zZRIoCgdyZWNlaXB0GAEgASgLMhcubWVjYXRsLnYxLkRyZWFtUmVjZWlwdCLLAQoPRHJlYW1SZXZpZXdQbGFuEgoKAmlkGAEgASgJEg4KBnRhcmdldBgCIAEoCRIuCgpleHBpcmVzX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIfChdwbGFubmVkX29wZXJhdGlvbl9jb3VudBgEIAEoBRIcChRwbGFubmVkX3NvdXJjZV9jb3VudBgFIAEoBRItCgpvcGVyYXRpb25zGAYgAygLMhkubWVjYXRsLnYxLkRyZWFtT3BlcmF0aW9uIt8BCg5EcmVhbU9wZXJhdGlvbhIMCgRraW5kGAEgASgJEi0KCHN1cnZpdm9yGAIgASgLMhsubWVjYXRsLnYxLkRyZWFtUGFydGljaXBhbnQSLAoHc291cmNlcxgDIAMoCzIbLm1lY2F0bC52MS5EcmVhbVBhcnRpY2lwYW50EjAKC3JlcGxhY2VtZW50GAQgASgLMhsubWVjYXRsLnYxLkRyZWFtUmVwbGFjZW1lbnQSDgoGcmVhc29uGAUgASgJEiAKGGV4YWN0X2R1cGxpY2F0ZV9lbGlnaWJsZRgGIAEoCCJDChBEcmVhbVBhcnRpY2lwYW50EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCSI2ChBEcmVhbVJlcGxhY2VtZW50Eg0KBXZhbHVlGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJItcBCgxEcmVhbVJlY2VpcHQSCgoCaWQYASABKAkSDgoGdGFyZ2V0GAIgASgJEhMKC2Rpc3Bvc2l0aW9uGAMgASgJEhwKFHBsYW5uZWRfc291cmNlX2NvdW50GAQgASgFEhwKFGFwcGxpZWRfc291cmNlX2NvdW50GAUgASgFEh8KF2NvbmZsaWN0ZWRfc291cmNlX2NvdW50GAYgASgFEhwKFHNraXBwZWRfc291cmNlX2NvdW50GAcgASgFEhsKE2ZhaWxlZF9zb3VyY2VfY291bnQYCCABKAUiNAoVQ29tcGFjdFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiKwoWQ29tcGFjdFNlc3Npb25SZXNwb25zZRIRCgljb21wYWN0ZWQYASABKAgiNwohV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkiTgohV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSFQoNZW5yb2xsbWVudF9pZBgCIAEoCSJxChNXb3Jrc3BhY2VFbnJvbGxtZW50EhUKDWVucm9sbG1lbnRfaWQYASABKAkSDgoGc3RhdHVzGAIgASgJEhkKEXJlcXVpcmVkX3NlcnZpY2VzGAMgASgNEhgKEHByZXNlbnRhdGlvbl91cmwYBCABKAkqvgEKDlBlcm1pc3Npb25Nb2RlEh8KG1BFUk1JU1NJT05fTU9ERV9VTlNQRUNJRklFRBAAEhsKF1BFUk1JU1NJT05fTU9ERV9ERUZBVUxUEAESGAoUUEVSTUlTU0lPTl9NT0RFX1BMQU4QAhIgChxQRVJNSVNTSU9OX01PREVfQUNDRVBUX0VESVRTEAMSGAoUUEVSTUlTU0lPTl9NT0RFX0FVVE8QBBIYChRQRVJNSVNTSU9OX01PREVfWU9MTxAFKpIBCg9BcHByb3ZhbFZlcmRpY3QSIAocQVBQUk9WQUxfVkVSRElDVF9VTlNQRUNJRklFRBAAEhkKFUFQUFJPVkFMX1ZFUkRJQ1RfREVOWRABEh8KG0FQUFJPVkFMX1ZFUkRJQ1RfQUxMT1dfT05DRRACEiEKHUFQUFJPVkFMX1ZFUkRJQ1RfQUxMT1dfQUxXQVlTEAMqvgEKDFN0ZWVyT3V0Y29tZRIdChlTVEVFUl9PVVRDT01FX1VOU1BFQ0lGSUVEEAASGgoWU1RFRVJfT1VUQ09NRV9BQ0NFUFRFRBABEhoKFlNURUVSX09VVENPTUVfQVBQRU5ERUQQAhIbChdTVEVFUl9PVVRDT01FX1JFVFJBQ1RFRBADEh4KGlNURUVSX09VVENPTUVfTk9ORV9QRU5ESU5HEAQSGgoWU1RFRVJfT1VUQ09NRV9UT09fTEFURRAFKoABCgxHdWFyZHJhaWxKb2ISHQoZR1VBUkRSQUlMX0pPQl9VTlNQRUNJRklFRBAAEhgKFEdVQVJEUkFJTF9KT0JfQUNUSU9OEAESGQoVR1VBUkRSQUlMX0pPQl9JTkJPVU5EEAISHAoYR1VBUkRSQUlMX0pPQl9QRVJNSVNTSU9OEAMqqgEKE0d1YXJkcmFpbEFzc2Vzc21lbnQSJAogR1VBUkRSQUlMX0FTU0VTU01FTlRfVU5TUEVDSUZJRUQQABIjCh9HVUFSRFJBSUxfQVNTRVNTTUVOVF9BQ0NFUFRBQkxFEAESIwofR1VBUkRSQUlMX0FTU0VTU01FTlRfUFJPSElCSVRFRBACEiMKH0dVQVJEUkFJTF9BU1NFU1NNRU5UX1VOUkVTT0xWRUQQAyqMAQoTR3VhcmRyYWlsSW5zcGVjdGlvbhIkCiBHVUFSRFJBSUxfSU5TUEVDVElPTl9VTlNQRUNJRklFRBAAEiEKHUdVQVJEUkFJTF9JTlNQRUNUSU9OX0NPTVBMRVRFEAESLAooR1VBUkRSQUlMX0lOU1BFQ1RJT05fT1BFUkFUSU9OQUxfRkFJTFVSRRACKtACChRHdWFyZHJhaWxEaXNwb3NpdGlvbhIlCiFHVUFSRFJBSUxfRElTUE9TSVRJT05fVU5TUEVDSUZJRUQQABIhCh1HVUFSRFJBSUxfRElTUE9TSVRJT05fRVhFQ1VURRABEiQKIEdVQVJEUkFJTF9ESVNQT1NJVElPTl9BU0tfQUNUSU9OEAISKQolR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1dJVEhIT0xEX1JFU1VMVBADEigKJEdVQVJEUkFJTF9ESVNQT1NJVElPTl9SRUxFQVNFX1JFU1VMVBAEEh4KGkdVQVJEUkFJTF9ESVNQT1NJVElPTl9ERU5ZEAUSJwojR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1BBU1NfQURWSVNPUlkQBhIqCiZHVUFSRFJBSUxfRElTUE9TSVRJT05fQ09OVElOVUVfV0FSTklORxAHKpABChVHdWFyZHJhaWxBcHByb3ZhbEtpbmQSJwojR1VBUkRSQUlMX0FQUFJPVkFMX0tJTkRfVU5TUEVDSUZJRUQQABIiCh5HVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9BQ1RJT04QARIqCiZHVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9SRVNVTFRfUkVMRUFTRRACKpgBCgxIb29rRGVjaXNpb24SHQoZSE9PS19ERUNJU0lPTl9VTlNQRUNJRklFRBAAEhYKEkhPT0tfREVDSVNJT05fSU5GTxABEhkKFUhPT0tfREVDSVNJT05fQkxPQ0tFRBACEhoKFkhPT0tfREVDSVNJT05fTU9ESUZJRUQQAxIaChZIT09LX0RFQ0lTSU9OX0FEVklTT1JZEAQqlgEKEFJldHJ5RGlzcG9zaXRpb24SIQodUkVUUllfRElTUE9TSVRJT05fVU5TUEVDSUZJRUQQABIdChlSRVRSWV9ESVNQT1NJVElPTl9VTktOT1dOEAESHwobUkVUUllfRElTUE9TSVRJT05fUkVUUllBQkxFEAISHwobUkVUUllfRElTUE9TSVRJT05fUEVSTUFORU5UEAMqqAEKDlN0cmVhbVByb2dyZXNzEh8KG1NUUkVBTV9QUk9HUkVTU19VTlNQRUNJRklFRBAAEhsKF1NUUkVBTV9QUk9HUkVTU19VTktOT1dOEAESHQoZU1RSRUFNX1BST0dSRVNTX1BSRUNPTU1JVBACEhsKF1NUUkVBTV9QUk9HUkVTU19WSVNJQkxFEAMSHAoYU1RSRUFNX1BST0dSRVNTX0NPTVBMRVRFEAQqhAEKDlNvdWxQcm92ZW5hbmNlEh8KG1NPVUxfUFJPVkVOQU5DRV9VTlNQRUNJRklFRBAAEhgKFFNPVUxfUFJPVkVOQU5DRV9VU0VSEAESGwoXU09VTF9QUk9WRU5BTkNFX1BST0pFQ1QQAhIaChZTT1VMX1BST1ZFTkFOQ0VfRFJJVkVSEAMqrQEKFFRlYW1NZW1iZXJTdG9wUmVhc29uEicKI1RFQU1fTUVNQkVSX1NUT1BfUkVBU09OX1VOU1BFQ0lGSUVEEAASIQodVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fRVJST1IQARIlCiFURUFNX01FTUJFUl9TVE9QX1JFQVNPTl9DQU5DRUxMRUQQAhIiCh5URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9CVURHRVQQAzKcOQoOSGFybmVzc1NlcnZpY2USZwoUR2V0Q29tcGF0aWJpbGl0eUluZm8SJi5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0GicubWVjYXRsLnYxLkdldENvbXBhdGliaWxpdHlJbmZvUmVzcG9uc2USbQoWTGlzdEV4ZWN1dGlvblRlbXBsYXRlcxIoLm1lY2F0bC52MS5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdBopLm1lY2F0bC52MS5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USUgoNQ3JlYXRlU2Vzc2lvbhIfLm1lY2F0bC52MS5DcmVhdGVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5DcmVhdGVTZXNzaW9uUmVzcG9uc2USUgoNR2V0U2VydmVySW5mbxIfLm1lY2F0bC52MS5HZXRTZXJ2ZXJJbmZvUmVxdWVzdBogLm1lY2F0bC52MS5HZXRTZXJ2ZXJJbmZvUmVzcG9uc2USSQoKR2V0U2Vzc2lvbhIcLm1lY2F0bC52MS5HZXRTZXNzaW9uUmVxdWVzdBodLm1lY2F0bC52MS5HZXRTZXNzaW9uUmVzcG9uc2USagoVTGlzdEd1YXJkcmFpbENvdmVyYWdlEicubWVjYXRsLnYxLkxpc3RHdWFyZHJhaWxDb3ZlcmFnZVJlcXVlc3QaKC5tZWNhdGwudjEuTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVzcG9uc2UScwoYR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsEioubWVjYXRsLnYxLkdldEd1YXJkcmFpbFJldmlld0RldGFpbFJlcXVlc3QaKy5tZWNhdGwudjEuR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVzcG9uc2USZwoUR2V0U2Vzc2lvblRyYW5zY3JpcHQSJi5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXF1ZXN0GicubWVjYXRsLnYxLkdldFNlc3Npb25UcmFuc2NyaXB0UmVzcG9uc2USQAoHU2V0TW9kZRIZLm1lY2F0bC52MS5TZXRNb2RlUmVxdWVzdBoaLm1lY2F0bC52MS5TZXRNb2RlUmVzcG9uc2USTwoMQ2xvc2VTZXNzaW9uEh4ubWVjYXRsLnYxLkNsb3NlU2Vzc2lvblJlcXVlc3QaHy5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVzcG9uc2USUgoNUmVuYW1lU2Vzc2lvbhIfLm1lY2F0bC52MS5SZW5hbWVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5SZW5hbWVTZXNzaW9uUmVzcG9uc2USUgoNRGVsZXRlU2Vzc2lvbhIfLm1lY2F0bC52MS5EZWxldGVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5EZWxldGVTZXNzaW9uUmVzcG9uc2USVQoOQ29tcGFjdFNlc3Npb24SIC5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXF1ZXN0GiEubWVjYXRsLnYxLkNvbXBhY3RTZXNzaW9uUmVzcG9uc2USTwoMQ2xlYXJTZXNzaW9uEh4ubWVjYXRsLnYxLkNsZWFyU2Vzc2lvblJlcXVlc3QaHy5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVzcG9uc2USTAoLRm9ya1Nlc3Npb24SHS5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXF1ZXN0Gh4ubWVjYXRsLnYxLkZvcmtTZXNzaW9uUmVzcG9uc2USRwoIQ29udmVyc2USGi5tZWNhdGwudjEuQ29udmVyc2VSZXF1ZXN0GhsubWVjYXRsLnYxLkNvbnZlcnNlUmVzcG9uc2UoATABElIKDVJlc29sdmVSdW5Bc2sSHy5tZWNhdGwudjEuUmVzb2x2ZVJ1bkFza1JlcXVlc3QaIC5tZWNhdGwudjEuUmVzb2x2ZVJ1bkFza1Jlc3BvbnNlElUKDlJlc29sdmVQbGFuQXNrEiAubWVjYXRsLnYxLlJlc29sdmVQbGFuQXNrUmVxdWVzdBohLm1lY2F0bC52MS5SZXNvbHZlUGxhbkFza1Jlc3BvbnNlEkYKCUNhbmNlbFJ1bhIbLm1lY2F0bC52MS5DYW5jZWxSdW5SZXF1ZXN0GhwubWVjYXRsLnYxLkNhbmNlbFJ1blJlc3BvbnNlEkMKCFN0ZWVyUnVuEhoubWVjYXRsLnYxLlN0ZWVyUnVuUmVxdWVzdBobLm1lY2F0bC52MS5TdGVlclJ1blJlc3BvbnNlElUKDkNhbmNlbFJ1blN0ZWVyEiAubWVjYXRsLnYxLkNhbmNlbFJ1blN0ZWVyUmVxdWVzdBohLm1lY2F0bC52MS5DYW5jZWxSdW5TdGVlclJlc3BvbnNlElsKEExpc3RNY3BSZXNvdXJjZXMSIi5tZWNhdGwudjEuTGlzdE1jcFJlc291cmNlc1JlcXVlc3QaIy5tZWNhdGwudjEuTGlzdE1jcFJlc291cmNlc1Jlc3BvbnNlElgKD1JlYWRNY3BSZXNvdXJjZRIhLm1lY2F0bC52MS5SZWFkTWNwUmVzb3VyY2VSZXF1ZXN0GiIubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlc3BvbnNlElUKDkxpc3RNY3BQcm9tcHRzEiAubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0TWNwUHJvbXB0c1Jlc3BvbnNlEk8KDEdldE1jcFByb21wdBIeLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlc3BvbnNlElUKDkxpc3RNY3BTb3VyY2VzEiAubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0TWNwU291cmNlc1Jlc3BvbnNlEl4KEVJlZnJlc2hNY3BTb3VyY2VzEiMubWVjYXRsLnYxLlJlZnJlc2hNY3BTb3VyY2VzUmVxdWVzdBokLm1lY2F0bC52MS5SZWZyZXNoTWNwU291cmNlc1Jlc3BvbnNlEnMKGExpc3RTZXNzaW9uTWNwQ29ubmVjdG9ycxIqLm1lY2F0bC52MS5MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXF1ZXN0GisubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1Jlc3BvbnNlEmEKEkxpc3RUb29sSGl2ZUdyb3VwcxIkLm1lY2F0bC52MS5MaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0GiUubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEkkKCkxpc3RBZ2VudHMSHC5tZWNhdGwudjEuTGlzdEFnZW50c1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdEFnZW50c1Jlc3BvbnNlEk8KDExpc3RDb21tYW5kcxIeLm1lY2F0bC52MS5MaXN0Q29tbWFuZHNSZXF1ZXN0Gh8ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1Jlc3BvbnNlElIKDUxpc3RXb3JrdHJlZXMSHy5tZWNhdGwudjEuTGlzdFdvcmt0cmVlc1JlcXVlc3QaIC5tZWNhdGwudjEuTGlzdFdvcmt0cmVlc1Jlc3BvbnNlElAKE1N0cmVhbVNlc3Npb25FdmVudHMSJS5tZWNhdGwudjEuU3RyZWFtU2Vzc2lvbkV2ZW50c1JlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJMChFTdHJlYW1TZXNzaW9uTGl2ZRIjLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uTGl2ZVJlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJjChJXYXRjaFNlc3Npb25FdmVudHMSJC5tZWNhdGwudjEuV2F0Y2hTZXNzaW9uRXZlbnRzUmVxdWVzdBolLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXNwb25zZTABEogBCh9HZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uEjEubWVjYXRsLnYxLkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXF1ZXN0GjIubWVjYXRsLnYxLkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRJ0ChdSZWNoZWNrTWNwQXV0aG9yaXphdGlvbhIpLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlcXVlc3QaKi5tZWNhdGwudjEuUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAEScQoWQ2FuY2VsTWNwQXV0aG9yaXphdGlvbhIoLm1lY2F0bC52MS5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVxdWVzdBopLm1lY2F0bC52MS5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVzcG9uc2UoATABEk8KDExpc3RTZXNzaW9ucxIeLm1lY2F0bC52MS5MaXN0U2Vzc2lvbnNSZXF1ZXN0Gh8ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1Jlc3BvbnNlElsKEEdldFN0b3JhZ2VIZWFsdGgSIi5tZWNhdGwudjEuR2V0U3RvcmFnZUhlYWx0aFJlcXVlc3QaIy5tZWNhdGwudjEuR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEmEKElBsYW5TZXNzaW9uQ2xlYW51cBIkLm1lY2F0bC52MS5QbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0GiUubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlc3BvbnNlElMKE0FwcGx5U2Vzc2lvbkNsZWFudXASJS5tZWNhdGwudjEuQXBwbHlTZXNzaW9uQ2xlYW51cFJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJVChRDYW5jZWxTZXNzaW9uQ2xlYW51cBImLm1lY2F0bC52MS5DYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJVChRHZXRTZXNzaW9uQ2xlYW51cEpvYhImLm1lY2F0bC52MS5HZXRTZXNzaW9uQ2xlYW51cEpvYlJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJJCgpMaXN0U2tpbGxzEhwubWVjYXRsLnYxLkxpc3RTa2lsbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RTa2lsbHNSZXNwb25zZRJVCg5MaXN0U2tpbGxGaWxlcxIgLm1lY2F0bC52MS5MaXN0U2tpbGxGaWxlc1JlcXVlc3QaIS5tZWNhdGwudjEuTGlzdFNraWxsRmlsZXNSZXNwb25zZRJSCg1SZWFkU2tpbGxGaWxlEh8ubWVjYXRsLnYxLlJlYWRTa2lsbEZpbGVSZXF1ZXN0GiAubWVjYXRsLnYxLlJlYWRTa2lsbEZpbGVSZXNwb25zZRJACgdHZXRTb3VsEhkubWVjYXRsLnYxLkdldFNvdWxSZXF1ZXN0GhoubWVjYXRsLnYxLkdldFNvdWxSZXNwb25zZRJPCgxHZXRVc2VyTW9kZWwSHi5tZWNhdGwudjEuR2V0VXNlck1vZGVsUmVxdWVzdBofLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXNwb25zZRJVCg5SZWZsZWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuUmVmbGVjdFNlc3Npb25SZXNwb25zZRJhChJHZXRMZWFybmluZ0F0dGVtcHQSJC5tZWNhdGwudjEuR2V0TGVhcm5pbmdBdHRlbXB0UmVxdWVzdBolLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJnChRMaXN0TGVhcm5pbmdBdHRlbXB0cxImLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1JlcXVlc3QaJy5tZWNhdGwudjEuTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRJpChRSZXRyeUxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmsKFkFiYW5kb25MZWFybmluZ0F0dGVtcHQSJy5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBooLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJeChFHZW5lcmF0ZURyZWFtUGxhbhIjLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlcXVlc3QaJC5tZWNhdGwudjEuR2VuZXJhdGVEcmVhbVBsYW5SZXNwb25zZRJYCg9EZWNpZGVEcmVhbVBsYW4SIS5tZWNhdGwudjEuRGVjaWRlRHJlYW1QbGFuUmVxdWVzdBoiLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXNwb25zZRJqChVMaXN0TGVhcm5pbmdQcm9wb3NhbHMSJy5tZWNhdGwudjEuTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVxdWVzdBooLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRJkChNHZXRMZWFybmluZ1Byb3Bvc2FsEiUubWVjYXRsLnYxLkdldExlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0GiYubWVjYXRsLnYxLkdldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRJtChZEZWNpZGVMZWFybmluZ1Byb3Bvc2FsEigubWVjYXRsLnYxLkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0GikubWVjYXRsLnYxLkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRJqChVVbmRvTGVhcm5pbmdQcm9tb3Rpb24SJy5tZWNhdGwudjEuVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVxdWVzdBooLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXNwb25zZRJeChFMaXN0TGVhcm5lZFNraWxscxIjLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1JlcXVlc3QaJC5tZWNhdGwudjEuTGlzdExlYXJuZWRTa2lsbHNSZXNwb25zZRJYCg9HZXRMZWFybmVkU2tpbGwSIS5tZWNhdGwudjEuR2V0TGVhcm5lZFNraWxsUmVxdWVzdBoiLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXNwb25zZRJzChhEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnMSKi5tZWNhdGwudjEuRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBorLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRJjChRBY3RpdmF0ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmEKElJlamVjdExlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmIKE0FyY2hpdmVMZWFybmVkU2tpbGwSJC5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJlChRSb2xsYmFja0xlYXJuZWRTa2lsbBImLm1lY2F0bC52MS5Sb2xsYmFja0xlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USWwoQTGlzdFNraWxsQ2hhbmdlcxIiLm1lY2F0bC52MS5MaXN0U2tpbGxDaGFuZ2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0U2tpbGxDaGFuZ2VzUmVzcG9uc2USSQoKTGlzdE1vZGVscxIcLm1lY2F0bC52MS5MaXN0TW9kZWxzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0TW9kZWxzUmVzcG9uc2USSQoKQ3JlYXRlVGVhbRIcLm1lY2F0bC52MS5DcmVhdGVUZWFtUmVxdWVzdBodLm1lY2F0bC52MS5DcmVhdGVUZWFtUmVzcG9uc2USUgoNU3Bhd25UZWFtbWF0ZRIfLm1lY2F0bC52MS5TcGF3blRlYW1tYXRlUmVxdWVzdBogLm1lY2F0bC52MS5TcGF3blRlYW1tYXRlUmVzcG9uc2USZAoTU2VuZFRlYW1tYXRlTWVzc2FnZRIlLm1lY2F0bC52MS5TZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBomLm1lY2F0bC52MS5TZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2USVQoOQ2FuY2VsVGVhbW1hdGUSIC5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0GiEubWVjYXRsLnYxLkNhbmNlbFRlYW1tYXRlUmVzcG9uc2USPAoHUnVuVGVhbRIZLm1lY2F0bC52MS5SdW5UZWFtUmVxdWVzdBoULm1lY2F0bC52MS5UZWFtRXZlbnQwARJDCghMaXN0VGVhbRIaLm1lY2F0bC52MS5MaXN0VGVhbVJlcXVlc3QaGy5tZWNhdGwudjEuTGlzdFRlYW1SZXNwb25zZRJMCgtDbGVhbnVwVGVhbRIdLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlcXVlc3QaHi5tZWNhdGwudjEuQ2xlYW51cFRlYW1SZXNwb25zZRJACgtBcHByb3ZlUGxhbhIdLm1lY2F0bC52MS5BcHByb3ZlUGxhblJlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJoChhDb25uZWN0V29ya3NwYWNlU2VydmljZXMSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaAoYUmV0cnlXb3Jrc3BhY2VFbnJvbGxtZW50EiwubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRDb250cm9sUmVxdWVzdBoeLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50EmkKGUNhbmNlbFdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRCogEKDWNvbS5tZWNhdGwudjFCDEhhcm5lc3NQcm90b1ABWj5naXRodWIuY29tL3N0YWNrbG9rL21lY2F0bC9jb250cmFjdHMvZ2VuL2dvL21lY2F0bC92MTttZWNhdGx2MaICA01YWKoCCU1lY2F0bC5WMcoCCU1lY2F0bFxWMeICFU1lY2F0bFxWMVxHUEJNZXRhZGF0YeoCCk1lY2F0bDo6VjFiBnByb3RvMw", [file_buf_validate_validate, file_google_protobuf_timestamp]); + fileDesc("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIpgDChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSMAoJZXhlY3V0aW9uGAwgASgLMh0ubWVjYXRsLnYxLkV4ZWN1dGlvblNlbGVjdGlvbhIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMSHQoVYWdlbnRfZGVmaW5pdGlvbl9uYW1lGA0gASgJSgQIARACSgQICBAJSgQIBhAHUgl3b3Jrc3BhY2VSEXNvdXJjZV9zZXNzaW9uX2lkUgdwcm9maWxlImwKEkV4ZWN1dGlvblNlbGVjdGlvbhImCgRub25lGAEgASgLMhgubWVjYXRsLnYxLkV4ZWN1dGlvbk5vbmUSLgoIdGVtcGxhdGUYAiABKAsyHC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGUiDwoNRXhlY3V0aW9uTm9uZSIxChFFeGVjdXRpb25UZW1wbGF0ZRIKCgJpZBgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCSIfCh1MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdCJtCh5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USLwoFaXRlbXMYASADKAsyIC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGVJbmZvEhoKEmludmVudG9yeV9yZXZpc2lvbhgCIAEoCSK9AgoVRXhlY3V0aW9uVGVtcGxhdGVJbmZvEi4KCHRlbXBsYXRlGAEgASgLMhwubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSFQoNZGlzcGxheV90b2tlbhgEIAEoCRJECgpleHRlbnNpb25zGAUgAygLMjAubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlSW5mby5FeHRlbnNpb25zRW50cnkSIAoYZGVjbGFyZWRfZXhlY3V0aW9uX2ZpbGVzGAYgASgIEh8KF2RlY2xhcmVkX2J1aWx0X2luX3NoZWxsGAcgASgIGjEKD0V4dGVuc2lvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIrEBCg1NY3BTZXJ2ZXJTcGVjEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEgwKBHR5cGUYAyABKAkSDwoHY29tbWFuZBgEIAEoCRI2CgdoZWFkZXJzGAUgAygLMiUubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMuSGVhZGVyc0VudHJ5Gi4KDEhlYWRlcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIisKFEdldFNlcnZlckluZm9SZXF1ZXN0EhMKC3Byb3ZpZGVyX2lkGAEgASgJIm8KFUdldFNlcnZlckluZm9SZXNwb25zZRIQCghidWlsZF9pZBgBIAEoCRIdChVzZXJ2ZXJfaW1wbGVtZW50YXRpb24YAiABKAkSJQodbGxtX3Byb3ZpZGVyX2Rpc3BsYXlfZW5kcG9pbnQYAyABKAkiHQobR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0IowBChxHZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEhEKCWFwaV9tYWpvchgBIAEoBRIzCgxjYXBhYmlsaXRpZXMYAiABKAsyHS5tZWNhdGwudjEuU2VydmVyQ2FwYWJpbGl0aWVzEhAKCGZlYXR1cmVzGAMgAygJEhIKCmRlcGxveW1lbnQYBCABKAki7wUKElNlcnZlckNhcGFiaWxpdGllcxILCgNtY3AYASABKAgSFgoOc2xhc2hfY29tbWFuZHMYAiABKAgSDgoGbWVtb3J5GAMgASgIEg4KBnNraWxscxgEIAEoCBINCgV0ZWFtcxgFIAEoCBINCgVzaGVsbBgGIAEoCBINCgVpbWFnZRgHIAEoCBINCgVhdWRpbxgIIAEoCBIOCgZhZ2VudHMYCSABKAgSDAoEc291bBgKIAEoCBISCgp1c2VyX21vZGVsGAsgASgIEhcKD21vZGVsX3NlbGVjdGlvbhgMIAEoCBIPCgdwb3N0dXJlGA0gASgJEhEKCXdvcmt0cmVlcxgOIAEoCBISCgpzY2hlZHVsaW5nGA8gASgIEhIKCnJlZmxlY3Rpb24YECABKAgSGgoSbGVhcm5pbmdfcHJvcG9zYWxzGBEgASgIEhYKDmxlYXJuZWRfc2tpbGxzGBIgASgIEhcKD3N0b3JhZ2VfY2xlYW51cBgWIAEoCBI4CgxtYW51YWxfZHJlYW0YEyABKAsyIi5tZWNhdGwudjEuTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSFgoOc3RvcmFnZV9oZWFsdGgYFyABKAgSDQoFc3RlZXIYGCABKAgSGQoRbWFudWFsX2NvbXBhY3Rpb24YGSABKAgSFQoNc2Vzc2lvbl9kZWJ1ZxgaIAEoCBIRCglkZWJ1Z19tY3AYGyABKAgSHAoUd29ya3NwYWNlX2Vucm9sbG1lbnQYHCABKAgSHAoUbWNwX2Nvbm5lY3Rvcl9zdGF0dXMYHSABKAgSEwoLbWNwX3JlZnJlc2gYHiABKAgSGwoTZXhlY3V0aW9uX3RlbXBsYXRlcxgfIAEoCBIcCg9wcm9qZWN0X3RydXN0ZWQYICABKAhIAIgBAUISChBfcHJvamVjdF90cnVzdGVkSgQIFBAVSgQIFRAWUg9sZWdhY3lfYWRvcHRpb25SEXN0b3JhZ2VfbWlncmF0aW9uIjUKH0xpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1JlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCSKyAQogTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVzcG9uc2USFAoMYXZhaWxhYmlsaXR5GAEgASgJEhgKEGVucm9sbG1lbnRfc3RhdGUYAiABKAkSMQoKY29ubmVjdG9ycxgDIAMoCzIdLm1lY2F0bC52MS5NY3BDb25uZWN0b3JTdGF0dXMSGAoQdG90YWxfY29ubmVjdG9ycxgEIAEoDRIRCgl0cnVuY2F0ZWQYBSABKAgiTwoSTWNwQ29ubmVjdG9yU3RhdHVzEgwKBG5hbWUYASABKAkSFwoPY2F0YWxvZ3VlX3N0YXRlGAIgASgJEhIKCnRvb2xfY291bnQYAyABKA0iiAIKFUNyZWF0ZVNlc3Npb25SZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEjwKFHNlc3Npb25fY2FwYWJpbGl0aWVzGAMgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25DYXBhYmlsaXRpZXMSMAoOcmVzb2x2ZWRfbW9kZWwYBCABKAsyGC5tZWNhdGwudjEuUmVzb2x2ZWRNb2RlbBIvCglwbGFjZW1lbnQYBSABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGESJgoecmVzb2x2ZWRfYWdlbnRfZGVmaW5pdGlvbl9uYW1lGAYgASgJSgQIAhADUgxjYXBhYmlsaXRpZXMiUgoRUGxhY2VtZW50TWV0YWRhdGESDAoEa2luZBgBIAEoCRINCgVsYWJlbBgCIAEoCRIOCgZicmFuY2gYAyABKAkSEAoIcmV2aXNpb24YBCABKAkiaAoNUmVzb2x2ZWRNb2RlbBITCgtwcm92aWRlcl9pZBgBIAEoCRIQCghtb2RlbF9pZBgCIAEoCRIWCg5jb250ZXh0X3dpbmRvdxgDIAEoAxIYChByZWFzb25pbmdfZWZmb3J0GAQgASgJImQKE1Nlc3Npb25DYXBhYmlsaXRpZXMSDQoFaW1hZ2UYASABKAgSDQoFYXVkaW8YAiABKAgSFwoPZXhlY3V0aW9uX2ZpbGVzGAMgASgIEhYKDmJ1aWx0X2luX3NoZWxsGAQgASgIIjAKEUdldFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiOQoSR2V0U2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiI6ChtHZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJSChRBY3Rpdml0eVJlcGxheVN0YXR1cxIRCglhdmFpbGFibGUYASABKAgSEAoIY29tcGxldGUYAiABKAgSFQoNYXV0aG9yaXRhdGl2ZRgDIAEoCCLtAQocR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEjAKCG1lc3NhZ2VzGAIgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2USEAoIY29tcGxldGUYAyABKAgSMQoIYWN0aXZpdHkYBCABKAsyHy5tZWNhdGwudjEuQWN0aXZpdHlSZXBsYXlTdGF0dXMSDAoEa2luZBgFIAEoCRI0CgxyZWxhdGlvbnNoaXAYBiABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcCI5ChpTdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjcKGFN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIlgKGVdhdGNoU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIOCgZjdXJzb3IYAiABKAkSDgoGcnVuX2lkGAMgASgJIlwKGldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50Eg4KBmN1cnNvchgCIAEoCRINCgVwaGFzZRgDIAEoCSI4ChNMaXN0U2Vzc2lvbnNSZXF1ZXN0EhEKCXBhZ2Vfc2l6ZRgBIAEoBRIOCgZjdXJzb3IYAiABKAkiTgoJUHJpbmNpcGFsEg4KBmlzc3VlchgBIAEoCRIPCgdzdWJqZWN0GAIgASgJEhIKCmdyYW50X3R5cGUYAyABKAkSDAoEbmFtZRgEIAEoCSL+BAoOU2Vzc2lvblN1bW1hcnkSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAIgASgDEg0KBXN0YXRlGAMgASgJEg0KBXR1cm5zGAQgASgFEhAKCG1vZGVsX2lkGAUgASgJEhcKD2NyZWF0ZWRfYXRfdW5peBgGIAEoAxIjCgVvd25lchgIIAEoCzIULm1lY2F0bC52MS5QcmluY2lwYWwSDAoEa2luZBgJIAEoCRI0CgxyZWxhdGlvbnNoaXAYCiABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBI9CgxjYXBhYmlsaXRpZXMYCyABKAsyJy5tZWNhdGwudjEuU2Vzc2lvbkludmVudG9yeUNhcGFiaWxpdGllcxITCgtyZWFzb25fY29kZRgMIAEoCRIvCglwbGFjZW1lbnQYDyABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGESLwoOdGl0bGVfbWV0YWRhdGEYECABKAsyFy5tZWNhdGwudjEuU2Vzc2lvblRpdGxlEj4KC3Rva2VuX3VzYWdlGBEgAygLMikubWVjYXRsLnYxLlNlc3Npb25TdW1tYXJ5LlRva2VuVXNhZ2VFbnRyeRIWCg5hY3Rpdml0eV9zdGF0ZRgSIAEoCRpICg9Ub2tlblVzYWdlRW50cnkSCwoDa2V5GAEgASgJEiQKBXZhbHVlGAIgASgLMhUubWVjYXRsLnYxLlRva2VuVXNhZ2U6AjgBSgQIBxAISgQIDRAOSgQIDhAPUgV0aXRsZVIJd29ya3NwYWNlUhB0aXRsZV9wcm92ZW5hbmNlIuYBChNTZXNzaW9uUmVsYXRpb25zaGlwEhkKEXBhcmVudF9zZXNzaW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSGQoMYnJhbmNoX2luZGV4GAMgASgFSACIAQESFQoNc2NoZWR1bGVfbmFtZRgEIAEoCRIZChFvcmlnaW5fc2Vzc2lvbl9pZBgFIAEoCRIPCgd0ZWFtX2lkGAYgASgJEhMKC21lbWJlcl9uYW1lGAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAggASgJQg8KDV9icmFuY2hfaW5kZXgikgIKHFNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcHVibGljX2NoYXQYASABKAgSDwoHaW5zcGVjdBgCIAEoCBIgChhhdXRob3JpdGF0aXZlX3RyYW5zY3JpcHQYAyABKAgSFwoPYWN0aXZpdHlfcmVwbGF5GAQgASgIEg8KB2NvcHlfaWQYBSABKAgSFwoPdmlld190cmFuc2NyaXB0GAYgASgIEgwKBGZvcmsYByABKAgSDgoGcmVuYW1lGAggASgIEg4KBmRlbGV0ZRgJIAEoCBI5CgdyZWFzb25zGAogASgLMigubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlBY3Rpb25SZWFzb25zIp0BCh1TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucxITCgtwdWJsaWNfY2hhdBgBIAEoCRIPCgdpbnNwZWN0GAIgASgJEg8KB2NvcHlfaWQYAyABKAkSFwoPdmlld190cmFuc2NyaXB0GAQgASgJEgwKBGZvcmsYBSABKAkSDgoGcmVuYW1lGAYgASgJEg4KBmRlbGV0ZRgHIAEoCSJtChRMaXN0U2Vzc2lvbnNSZXNwb25zZRIrCghzZXNzaW9ucxgBIAMoCzIZLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeRITCgtuZXh0X2N1cnNvchgCIAEoCRITCgt0b3RhbF9jb3VudBgDIAEoBSIZChdHZXRTdG9yYWdlSGVhbHRoUmVxdWVzdCLeAQoPUmV0ZW50aW9uUG9saWN5EhwKFG1haW5fbWF4X2FnZV9zZWNvbmRzGAEgASgDEhYKDm1haW5fbWF4X2NvdW50GAIgASgFEh0KFWNoaWxkX21heF9hZ2Vfc2Vjb25kcxgDIAEoAxIXCg9jaGlsZF9tYXhfY291bnQYBCABKAUSIQoZc2NoZWR1bGVkX21heF9hZ2Vfc2Vjb25kcxgFIAEoAxIbChNzY2hlZHVsZWRfbWF4X2NvdW50GAYgASgFEh0KFXN3ZWVwX2NhZGVuY2Vfc2Vjb25kcxgHIAEoAyLJBwoYR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEhEKCWF2YWlsYWJsZRgBIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAiABKAkSFQoNY3VycmVudF9ieXRlcxgDIAEoAxIfChdjdXJyZW50X2J5dGVzX2F2YWlsYWJsZRgEIAEoCBIZChFyZWNsYWltYWJsZV9ieXRlcxgFIAEoAxIjChtyZWNsYWltYWJsZV9ieXRlc19hdmFpbGFibGUYBiABKAgSFQoNc2Vzc2lvbl9jb3VudBgHIAEoAxISCgpmaWxlX2NvdW50GAggASgDEhAKCHYxX2NvdW50GAkgASgDEhAKCHYyX2NvdW50GAogASgDEhIKCm1haW5fY291bnQYCyABKAMSEwoLY2hpbGRfY291bnQYDCABKAMSFwoPc2NoZWR1bGVkX2NvdW50GA0gASgDEhUKDXVua25vd25fY291bnQYDiABKAMSFQoNY29ycnVwdF9jb3VudBgPIAEoAxIqCgZwb2xpY3kYECABKAsyGi5tZWNhdGwudjEuUmV0ZW50aW9uUG9saWN5EhcKD2xhc3Rfc3dlZXBfdW5peBgRIAEoAxIcChRsYXN0X3N3ZWVwX2F2YWlsYWJsZRgSIAEoCBIXCg9uZXh0X3N3ZWVwX3VuaXgYEyABKAMSHAoUbmV4dF9zd2VlcF9hdmFpbGFibGUYFCABKAgSEgoKYWN0aXZlX2pvYhgVIAEoCRIUCgxsYXN0X2ZhaWx1cmUYFiABKAkSJAocb3duZXJsZXNzX3Nlc3Npb25zX2F2YWlsYWJsZRgXIAEoCBItCiVvd25lcmxlc3Nfc2Vzc2lvbnNfdW5hdmFpbGFibGVfcmVhc29uGBggASgJEh8KF293bmVybGVzc19zZXNzaW9uX2NvdW50GBkgASgDEh0KFW93bmVybGVzc19zZXNzaW9uX2lkcxgaIAMoCRInCh9vd25lcmxlc3Nfc2Vzc2lvbl9pZHNfdHJ1bmNhdGVkGBsgASgIEiUKHW93bmVybGVzc19zY2hlZHVsZXNfYXZhaWxhYmxlGBwgASgIEi4KJm93bmVybGVzc19zY2hlZHVsZXNfdW5hdmFpbGFibGVfcmVhc29uGB0gASgJEiAKGG93bmVybGVzc19zY2hlZHVsZV9jb3VudBgeIAEoAxIgChhvd25lcmxlc3Nfc2NoZWR1bGVfbmFtZXMYHyADKAkSKgoib3duZXJsZXNzX3NjaGVkdWxlX25hbWVzX3RydW5jYXRlZBggIAEoCCLZAgoNQ2xlYW51cENvdW50cxINCgV0b3RhbBgBIAEoBRI1CgdieV9raW5kGAIgAygLMiQubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlLaW5kRW50cnkSNwoIYnlfc3RhdGUYAyADKAsyJS5tZWNhdGwudjEuQ2xlYW51cENvdW50cy5CeVN0YXRlRW50cnkSOQoJYnlfcmVhc29uGAQgAygLMiYubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlSZWFzb25FbnRyeRotCgtCeUtpbmRFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAU6AjgBGi4KDEJ5U3RhdGVFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAU6AjgBGi8KDUJ5UmVhc29uRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ASKGAQoQQ2xlYW51cENhbmRpZGF0ZRISCgpzZXNzaW9uX2lkGAEgASgJEgwKBGtpbmQYAiABKAkSDQoFc3RhdGUYAyABKAkSDgoGcmVhc29uGAQgASgJEhgKEG1vZGlmaWVkX2F0X3VuaXgYBSABKAMSFwoPZXN0aW1hdGVkX2J5dGVzGAYgASgDIioKGVBsYW5TZXNzaW9uQ2xlYW51cFJlcXVlc3QSDQoFa2luZHMYASADKAki0wIKGlBsYW5TZXNzaW9uQ2xlYW51cFJlc3BvbnNlEhoKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCRIRCglhdmFpbGFibGUYAiABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAMgASgJEhIKCmdlbmVyYXRpb24YBCABKAkSFgoOcG9saWN5X3ZlcnNpb24YBSABKAkSLQoIZWxpZ2libGUYBiADKAsyGy5tZWNhdGwudjEuQ2xlYW51cENhbmRpZGF0ZRIrCglwcm90ZWN0ZWQYByABKAsyGC5tZWNhdGwudjEuQ2xlYW51cENvdW50cxIXCg9lc3RpbWF0ZWRfYnl0ZXMYCCABKAMSFgoOcGxhbm5lZF9qb2JfaWQYCSABKAkSMQoPZWxpZ2libGVfY291bnRzGAogASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMiQQoaQXBwbHlTZXNzaW9uQ2xlYW51cFJlcXVlc3QSIwoSY29uZmlybWF0aW9uX3Rva2VuGAEgASgJQge6SARyAhABIjYKG0NhbmNlbFNlc3Npb25DbGVhbnVwUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiNgobR2V0U2Vzc2lvbkNsZWFudXBKb2JSZXF1ZXN0EhcKBmpvYl9pZBgBIAEoCUIHukgEcgIQASJNChBDbGVhbnVwSXRlbUVycm9yEhMKC2l0ZW1faGFuZGxlGAEgASgJEhMKC3JlYXNvbl9jb2RlGAIgASgJEg8KB21lc3NhZ2UYAyABKAkirAEKCkNsZWFudXBKb2ISDgoGam9iX2lkGAEgASgJEg0KBXN0YXRlGAIgASgJEhEKCXByb2Nlc3NlZBgDIAEoBRIPCgdkZWxldGVkGAQgASgFEg8KB3NraXBwZWQYBSABKAUSDQoFc3RhbGUYBiABKAUSDgoGZmFpbGVkGAcgASgFEisKBmVycm9ycxgIIAMoCzIbLm1lY2F0bC52MS5DbGVhbnVwSXRlbUVycm9yIlYKDlNldE1vZGVSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESJwoEbW9kZRgCIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZSI2Cg9TZXRNb2RlUmVzcG9uc2USIwoHc2Vzc2lvbhgBIAEoCzISLm1lY2F0bC52MS5TZXNzaW9uIjIKE0Nsb3NlU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASIWChRDbG9zZVNlc3Npb25SZXNwb25zZSJLChRSZW5hbWVTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEhYKBXRpdGxlGAIgASgJQge6SARyAhABIjwKFVJlbmFtZVNlc3Npb25SZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iMwoURGVsZXRlU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASIXChVEZWxldGVTZXNzaW9uUmVzcG9uc2UibwoTQ2xlYXJTZXNzaW9uUmVxdWVzdBIiChFzb3VyY2Vfc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIeChF3b3JrdHJlZV9zZWxlY3RvchgCIAEoCUgAiAEBQhQKEl93b3JrdHJlZV9zZWxlY3RvciJbChRDbGVhclNlc3Npb25SZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEi8KCXBsYWNlbWVudBgCIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YSK+AQoSRm9ya1Nlc3Npb25SZXF1ZXN0EiIKEXNvdXJjZV9zZXNzaW9uX2lkGAEgASgJQge6SARyAhABEg0KBXRpdGxlGAIgASgJEhgKEHJlYXNvbmluZ19lZmZvcnQYAyABKAkSHgoRd29ya3RyZWVfc2VsZWN0b3IYBCABKAlIAIgBARITCgtwcm92aWRlcl9pZBgFIAEoCRIQCghtb2RlbF9pZBgGIAEoCUIUChJfd29ya3RyZWVfc2VsZWN0b3IiWgoTRm9ya1Nlc3Npb25SZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEi8KCXBsYWNlbWVudBgCIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YSI7ChBDb250ZXh0T2NjdXBhbmN5EhQKDGlucHV0X3Rva2VucxgBIAEoAxIRCgllc3RpbWF0ZWQYAiABKAgirAYKB1Nlc3Npb24SEgoKc2Vzc2lvbl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRInCgRtb2RlGAMgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgFIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSDQoFdHVybnMYBiABKAUSEgoKdG9vbF9jYWxscxgHIAEoBRIXCg9jcmVhdGVkX2F0X3VuaXgYCCABKAMSMAoOcmVzb2x2ZWRfbW9kZWwYCSABKAsyGC5tZWNhdGwudjEuUmVzb2x2ZWRNb2RlbBIMCgRraW5kGA4gASgJEjQKDHJlbGF0aW9uc2hpcBgPIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uUmVsYXRpb25zaGlwEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGBAgAygJEhcKD2RlYnVnX21jcF90b29scxgRIAMoCRIvCglwbGFjZW1lbnQYEiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGESLwoOdGl0bGVfbWV0YWRhdGEYEyABKAsyFy5tZWNhdGwudjEuU2Vzc2lvblRpdGxlEjcKC3Rva2VuX3VzYWdlGBQgAygLMiIubWVjYXRsLnYxLlNlc3Npb24uVG9rZW5Vc2FnZUVudHJ5EjwKFHNlc3Npb25fY2FwYWJpbGl0aWVzGBUgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25DYXBhYmlsaXRpZXMSPQoYbGF0ZXN0X2NvbnRleHRfb2NjdXBhbmN5GBYgASgLMhsubWVjYXRsLnYxLkNvbnRleHRPY2N1cGFuY3kaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECAQQBUoECAoQC0oECAsQDEoECAwQDUoECA0QDlIJd29ya3NwYWNlUgV0aXRsZVIMY2FwYWJpbGl0aWVzUhB0aXRsZV9wcm92ZW5hbmNlUhphZG9wdGlvbl9zb3VyY2Vfc2Vzc2lvbl9pZCKVAQoMU2Vzc2lvblRpdGxlEg0KBXRpdGxlGAEgASgJEhIKCnByb3ZlbmFuY2UYAiABKAkSGAoQZ2VuZXJhdGlvbl9zdGF0ZRgDIAEoCRI2Cg5sYXRlc3RfYXR0ZW1wdBgEIAEoCzIeLm1lY2F0bC52MS5UaXRsZUF0dGVtcHRTdW1tYXJ5EhAKCHJldmlzaW9uGAUgASgEIjgKE1RpdGxlQXR0ZW1wdFN1bW1hcnkSCgoCaWQYASABKAkSDwoHb3V0Y29tZRgCIAEoCUoECAMQBCKhAQoKVG9rZW5Vc2FnZRIfCgV0b3RhbBgBIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIxCgZtb2RlbHMYAiADKAsyIS5tZWNhdGwudjEuVG9rZW5Vc2FnZS5Nb2RlbHNFbnRyeRo/CgtNb2RlbHNFbnRyeRILCgNrZXkYASABKAkSHwoFdmFsdWUYAiABKAsyEC5tZWNhdGwudjEuVXNhZ2U6AjgBIsQCCg9Db252ZXJzZVJlcXVlc3QSIwoGcHJvbXB0GAEgASgLMhEubWVjYXRsLnYxLlByb21wdEgAEiYKBXJldHJ5GAIgASgLMhUubWVjYXRsLnYxLlJldHJ5U3RhcnRIABI0Cg9yZXN1bWVfYXBwcm92YWwYCiABKAsyGS5tZWNhdGwudjEuUmVzdW1lQXBwcm92YWxIABIjCgZjYW5jZWwYCyABKAsyES5tZWNhdGwudjEuQ2FuY2VsSAASLgoMY2FuY2VsX2NoaWxkGAwgASgLMhYubWVjYXRsLnYxLkNhbmNlbENoaWxkSAASIQoFc3RlZXIYDSABKAsyEC5tZWNhdGwudjEuU3RlZXJIABIuCgxzdGVlcl9jYW5jZWwYDiABKAsyFi5tZWNhdGwudjEuU3RlZXJDYW5jZWxIAEIGCgRraW5kIjMKEENvbnZlcnNlUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQinAEKB0NvbnRlbnQSJQoEa2luZBgBIAEoDjIXLm1lY2F0bC52MS5Db250ZW50LktpbmQSEQoJbWltZV90eXBlGAIgASgJEgwKBGRhdGEYAyABKAwSCwoDdXJsGAQgASgJIjwKBEtpbmQSFAoQS0lORF9VTlNQRUNJRklFRBAAEg4KCktJTkRfSU1BR0UQARIOCgpLSU5EX0FVRElPEAIikAMKDENvbnRlbnRCbG9jaxIqCgRraW5kGAEgASgOMhwubWVjYXRsLnYxLkNvbnRlbnRCbG9jay5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCRIMCgR0ZXh0GAUgASgJEgwKBG5hbWUYBiABKAkSDQoFdGl0bGUYByABKAkSEwoLZGVzY3JpcHRpb24YCCABKAkSDAoEc2l6ZRgJIAEoAxIQCghhdWRpZW5jZRgKIAMoCRIQCghwcmlvcml0eRgLIAEoARIVCg1sYXN0X21vZGlmaWVkGAwgASgJIpwBCgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABINCglLSU5EX1RFWFQQARIOCgpLSU5EX0lNQUdFEAISDgoKS0lORF9BVURJTxADEhYKEktJTkRfUkVTT1VSQ0VfTElOSxAEEhoKFktJTkRfRU1CRURERURfUkVTT1VSQ0UQBRIbChdLSU5EX1NUUlVDVFVSRURfQ09OVEVOVBAGIikKClJldHJ5U3RhcnQSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJ+CgZQcm9tcHQSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIMCgR0ZXh0GAIgASgJEiEKBXBhcnRzGAMgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSJgoec2VydmVyX293bmVkX3BsYW5fY29udGludWF0aW9uGAQgASgIItcBCg5SZXN1bWVBcHByb3ZhbBIXCgZhc2tfaWQYASABKAlCB7pIBHICEAESOQoHdmVyZGljdBgDIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAxIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkSEQoJcmV2aWV3X2lkGAUgASgJEjgKDmd1YXJkcmFpbF9raW5kGAYgASgOMiAubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsS2luZEoECAIQA1IFYWxsb3ciIQoGQ2FuY2VsEhcKD2V4cGVjdGVkX3J1bl9pZBgBIAEoCSIoCgtDYW5jZWxDaGlsZBIZCghjaGlsZF9pZBgBIAEoCUIHukgEcgIQASJlCgVTdGVlchIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudBIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkiOgoLU3RlZXJDYW5jZWwSEgoKbWVzc2FnZV9pZBgBIAEoCRIXCg9leHBlY3RlZF9ydW5faWQYAiABKAki9gEKFFJlc29sdmVSdW5Bc2tSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIAoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJQge6SARyAhABEhcKBmFza19pZBgDIAEoCUIHukgEcgIQARI5Cgd2ZXJkaWN0GAQgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdEIMukgJggEGGAEYAhgDEhEKCXJldmlld19pZBgFIAEoCRI4Cg5ndWFyZHJhaWxfa2luZBgGIAEoDjIgLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbEtpbmQiNwoVUmVzb2x2ZVJ1bkFza1Jlc3BvbnNlEg4KBnJ1bl9pZBgBIAEoCRIOCgZhc2tfaWQYAiABKAkiqgEKFVJlc29sdmVQbGFuQXNrUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIXCgZhc2tfaWQYAyABKAlCB7pIBHICEAESOQoHdmVyZGljdBgEIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAyI4ChZSZXNvbHZlUGxhbkFza1Jlc3BvbnNlEg4KBnJ1bl9pZBgBIAEoCRIOCgZhc2tfaWQYAiABKAkiUQoQQ2FuY2VsUnVuUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQASIjChFDYW5jZWxSdW5SZXNwb25zZRIOCgZydW5faWQYASABKAkikAIKD1N0ZWVyUnVuUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIMCgR0ZXh0GAMgASgJEisKBXBhcnRzGAQgAygLMhIubWVjYXRsLnYxLkNvbnRlbnRCCLpIBZIBAhAQEhsKCm1lc3NhZ2VfaWQYBSABKAlCB7pIBHICGEA6ZrpIYxphChFzdGVlcl9ydW4uY29udGVudBIjdGV4dCBhbmQgcGFydHMgY2Fubm90IGJvdGggYmUgZW1wdHkaJ3RoaXMudGV4dCAhPSAnJyB8fCBzaXplKHRoaXMucGFydHMpID4gMCJgChBTdGVlclJ1blJlc3BvbnNlEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEg4KBnJ1bl9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJInMKFUNhbmNlbFJ1blN0ZWVyUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIbCgptZXNzYWdlX2lkGAMgASgJQge6SARyAhhAImYKFkNhbmNlbFJ1blN0ZWVyUmVzcG9uc2USKAoHb3V0Y29tZRgBIAEoDjIXLm1lY2F0bC52MS5TdGVlck91dGNvbWUSDgoGcnVuX2lkGAIgASgJEhIKCm1lc3NhZ2VfaWQYAyABKAkiaAomR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIhChBhdXRob3JpemF0aW9uX2lkGAIgASgJQge6SARyAhABIjYKJ0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRILCgN1cmwYASABKAkitAEKHlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhgKEGF1dGhvcml6YXRpb25faWQYAiABKAkSNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAQgkKB2NvbnRyb2wiQgofUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKzAQodQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkEKHkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKQAQoNQXV0aG9yaXphdGlvbhIYChBhdXRob3JpemF0aW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGc3RhdHVzGAQgASgJEhQKDGRpc3BsYXlfbmFtZRgFIAEoCSI+ChdQbGFuQ29udGludWF0aW9uRmFpbHVyZRITCgtwbGFuX3J1bl9pZBgBIAEoCRIOCgZhc2tfaWQYAiABKAkitwcKBUV2ZW50EgwKBHR5cGUYASABKAkSCwoDc2VxGAIgASgDEgwKBHR1cm4YAyABKAUSDAoEdGV4dBgEIAEoCRImCgl0b29sX2NhbGwYBSABKAsyEy5tZWNhdGwudjEuVG9vbENhbGwSKgoLdG9vbF9yZXN1bHQYBiABKAsyFS5tZWNhdGwudjEuVG9vbFJlc3VsdBIlCgNhc2sYByABKAsyGC5tZWNhdGwudjEuUGVybWlzc2lvbkFzaxIhCgZyZXN1bHQYCCABKAsyES5tZWNhdGwudjEuUmVzdWx0EiQKCHR1cm5fZW5kGAogASgLMhIubWVjYXRsLnYxLlR1cm5FbmQSHQoEaG9vaxgLIAEoCzIPLm1lY2F0bC52MS5Ib29rEiUKCHN1YmFnZW50GAwgASgLMhMubWVjYXRsLnYxLlN1YmFnZW50Eh0KBHRlYW0YDSABKAsyDy5tZWNhdGwudjEuVGVhbRIlCghwYXJhbGxlbBgOIAEoCzITLm1lY2F0bC52MS5QYXJhbGxlbBIsCghzY2hlZHVsZRgPIAEoCzIaLm1lY2F0bC52MS5TY2hlZHVsZVBheWxvYWQSJQoIYXBwcm92YWwYECABKAsyEy5tZWNhdGwudjEuQXBwcm92YWwSKgoLdXNlcl9wcm9tcHQYESABKAsyFS5tZWNhdGwudjEuVXNlclByb21wdBI4ChJjb21wYWN0aW9uX2FyY2hpdmUYEiABKAsyHC5tZWNhdGwudjEuQ29tcGFjdGlvbkFyY2hpdmUSIwoFc3RlZXIYEyABKAsyFC5tZWNhdGwudjEuU3RlZXJFY2hvEioKDXN0ZWVyX291dGNvbWUYFCABKAsyEy5tZWNhdGwudjEuU3RlZXJBY2sSKgoLbW9kZWxfcmV0cnkYFSABKAsyFS5tZWNhdGwudjEuTW9kZWxSZXRyeRIOCgZydW5faWQYFiABKAkSJgoFdGl0bGUYFyABKAsyFy5tZWNhdGwudjEuU2Vzc2lvblRpdGxlEi8KDWF1dGhvcml6YXRpb24YGCABKAsyGC5tZWNhdGwudjEuQXV0aG9yaXphdGlvbhIyCg9jb250cm9sX3JlZnVzZWQYGSABKAsyGS5tZWNhdGwudjEuQ29udHJvbFJlZnVzZWQSRQoZcGxhbl9jb250aW51YXRpb25fZmFpbHVyZRgaIAEoCzIiLm1lY2F0bC52MS5QbGFuQ29udGludWF0aW9uRmFpbHVyZUoECAkQClIFdXNhZ2UiMgoOQ29udHJvbFJlZnVzZWQSDgoGYXNrX2lkGAEgASgJEhAKCGNhdGVnb3J5GAIgASgJIngKCk1vZGVsUmV0cnkSNgoRcmV0cnlfZGlzcG9zaXRpb24YASABKA4yGy5tZWNhdGwudjEuUmV0cnlEaXNwb3NpdGlvbhIyCg9zdHJlYW1fcHJvZ3Jlc3MYAiABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3MiUAoJU3RlZXJFY2hvEgwKBHRleHQYASABKAkSEgoKbWVzc2FnZV9pZBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50ImgKCFN0ZWVyQWNrEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEgwKBHRleHQYAiABKAkSEAoIcHJvbW90ZWQYAyABKAgSEgoKbWVzc2FnZV9pZBgEIAEoCSItCgxHdWFyZHJhaWxSZWYSCwoDcmVmGAEgASgJEhAKCGNhdGVnb3J5GAIgASgJIq8DCg9HdWFyZHJhaWxSZXZpZXcSEQoJcmV2aWV3X2lkGAEgASgJEiQKA2pvYhgCIAEoDjIXLm1lY2F0bC52MS5HdWFyZHJhaWxKb2ISMgoKYXNzZXNzbWVudBgDIAEoDjIeLm1lY2F0bC52MS5HdWFyZHJhaWxBc3Nlc3NtZW50EjIKCmluc3BlY3Rpb24YBCABKA4yHi5tZWNhdGwudjEuR3VhcmRyYWlsSW5zcGVjdGlvbhI0CgtkaXNwb3NpdGlvbhgFIAEoDjIfLm1lY2F0bC52MS5HdWFyZHJhaWxEaXNwb3NpdGlvbhITCgtyZWFzb25fY29kZRgGIAEoCRIPCgdydWxlX2lkGAcgASgJEhMKC3J1bGVfb3JpZ2luGAggASgJEhsKE2NoZWNrZXJfcHJvdmlkZXJfaWQYCSABKAkSGAoQY2hlY2tlcl9tb2RlbF9pZBgKIAEoCRIpCghjb25jZXJucxgLIAMoCzIXLm1lY2F0bC52MS5HdWFyZHJhaWxSZWYSKAoHc291cmNlcxgMIAMoCzIXLm1lY2F0bC52MS5HdWFyZHJhaWxSZWYipwEKFkd1YXJkcmFpbEFwcHJvdmFsU2NvcGUSEQoJcmV2aWV3X2lkGAEgASgJEi4KBGtpbmQYAiABKA4yIC5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxLaW5kEhQKDGdyYW50X2RpZ2VzdBgDIAEoCRIUCgxzZXNzaW9uX29ubHkYBCABKAgSGAoQcmVwZWF0X2F2YWlsYWJsZRgFIAEoCEoECAYQByIyChxMaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAki0wEKFkd1YXJkcmFpbENvdmVyYWdlRW50cnkSDAoEdG9vbBgBIAEoCRINCgVwaGFzZRgCIAEoCRIkCgNqb2IYAyABKA4yFy5tZWNhdGwudjEuR3VhcmRyYWlsSm9iEgwKBG1vZGUYBCABKAkSDwoHcnVsZV9pZBgFIAEoCRITCgtydWxlX29yaWdpbhgGIAEoCRIyCgppbnNwZWN0aW9uGAcgASgOMh4ubWVjYXRsLnYxLkd1YXJkcmFpbEluc3BlY3Rpb24SDgoGcmVhc29uGAggASgJIpsBCh1MaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXNwb25zZRIPCgdlbmFibGVkGAEgASgIEhsKE2NoZWNrZXJfcHJvdmlkZXJfaWQYAiABKAkSGAoQY2hlY2tlcl9tb2RlbF9pZBgDIAEoCRIyCgdlbnRyaWVzGAQgAygLMiEubWVjYXRsLnYxLkd1YXJkcmFpbENvdmVyYWdlRW50cnkiSAofR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhEKCXJldmlld19pZBgCIAEoCSJzCiBHZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXNwb25zZRIRCglyZXZpZXdfaWQYASABKAkSDwoHY29uY2VybhgCIAEoCRIWCg5zb3VyY2VfZGlzcGxheRgDIAEoCRITCgtuZXh0X2FjdGlvbhgEIAEoCSKQAQoIQXBwcm92YWwSDgoGYXNrX2lkGAEgASgJEgwKBHRvb2wYAyABKAkSDwoHY2FsbF9pZBgEIAEoCRIrCgd2ZXJkaWN0GAYgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdBIOCgZvcmlnaW4YByABKAlKBAgCEANKBAgFEAZSDGFsbG93X2Fsd2F5cyJQCgpVc2VyUHJvbXB0EgwKBHRleHQYASABKAkSIQoFcGFydHMYAiADKAsyEi5tZWNhdGwudjEuQ29udGVudBIRCglzeW50aGV0aWMYAyABKAgiRQoRQ29tcGFjdGlvbkFyY2hpdmUSMAoIcmVwbGFjZWQYASADKAsyHi5tZWNhdGwudjEuQ29udmVyc2F0aW9uTWVzc2FnZSLvAQoTQ29udmVyc2F0aW9uTWVzc2FnZRIMCgRyb2xlGAEgASgJEgwKBHRleHQYAiABKAkSJwoKdG9vbF9jYWxscxgDIAMoCzITLm1lY2F0bC52MS5Ub29sQ2FsbBIqCgt0b29sX3Jlc3VsdBgEIAEoCzIVLm1lY2F0bC52MS5Ub29sUmVzdWx0EhEKCXJlYXNvbmluZxgFIAEoCRIWCg5wcm92aWRlcl9waGFzZRgGIAEoCRIhCgVwYXJ0cxgHIAMoCzISLm1lY2F0bC52MS5Db250ZW50EhkKEXJlYXNvbmluZ19pdGVtX2lkGAggASgJInYKD1NjaGVkdWxlUGF5bG9hZBIVCg1zY2hlZHVsZV9uYW1lGAEgASgJEg8KB2ZpcmVfaWQYAiABKAkSEgoKc2Vzc2lvbl9pZBgDIAEoCRIMCgRraW5kGAQgASgJEgwKBHN0b3AYBSABKAkSCwoDZXJyGAYgASgJIo4BCgRIb29rEg0KBXBoYXNlGAEgASgJEgwKBHRvb2wYAiABKAkSKQoIZGVjaXNpb24YAyABKA4yFy5tZWNhdGwudjEuSG9va0RlY2lzaW9uEg8KB2NhbGxfaWQYBCABKAkSLQoJZ3VhcmRyYWlsGAUgASgLMhoubWVjYXRsLnYxLkd1YXJkcmFpbFJldmlldyKoAgoPUm91dGluZ0RlY2lzaW9uEg8KB2JhY2tlbmQYASABKAkSGAoQY2xhc3NpZmllcl9tb2RlbBgCIAEoCRIaChJjYW5kaWRhdGVfY2F0ZWdvcnkYAyABKAkSFwoPY2FuZGlkYXRlX21vZGVsGAQgASgJEhcKCmNvbmZpZGVuY2UYBSABKAFIAIgBARIfChJtaW5pbXVtX2NvbmZpZGVuY2UYBiABKAFIAYgBARIPCgdvdXRjb21lGAcgASgJEhoKEmNvbnNlY3V0aXZlX21pc3NlcxgIIAEoBRISCgptaXNzX2xpbWl0GAkgASgFEhQKDGJyZWFrZXJfb3BlbhgKIAEoCEINCgtfY29uZmlkZW5jZUIVChNfbWluaW11bV9jb25maWRlbmNlIooECghTdWJhZ2VudBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIQCghjaGlsZF9pZBgCIAEoCRIMCgRnb2FsGAMgASgJEhEKCXRvb2xfbmFtZRgEIAEoCRIQCghpc19lcnJvchgFIAEoCBISCgp0b29sX2NvdW50GAYgASgFEh8KBXVzYWdlGAcgASgLMhAubWVjYXRsLnYxLlVzYWdlEgwKBHN0b3AYCCABKAkSEwoLZHVyYXRpb25fbXMYCSABKAMSEgoKYmFja2dyb3VuZBgKIAEoCBIXCg9yb3V0ZWRfY2F0ZWdvcnkYCyABKAkSFAoMcm91dGVkX21vZGVsGAwgASgJEg0KBW1vZGVsGA0gASgJEhIKCmlubmVyX2tpbmQYDiABKAkSDAoEdGV4dBgPIAEoCRIOCgZkZXRhaWwYECABKAkSDQoFY2F1c2UYESABKAkSFgoOcm91dGluZ19yZWFzb24YEiABKAkSOQoQcm91dGluZ19kZWNpc2lvbhgTIAEoCzIaLm1lY2F0bC52MS5Sb3V0aW5nRGVjaXNpb25IAIgBARIaChJjaGlsZF90b29sX2NhbGxfaWQYFCABKAkSEAoIcHJvdmlkZXIYFSABKAkSIAoYZXhwbGljaXRfcm91dGVyX2NhdGVnb3J5GBYgASgJQhMKEV9yb3V0aW5nX2RlY2lzaW9uIqYCCg5UZWFtTWVtYmVyU3BlYxIMCgRuYW1lGAEgASgJEgwKBHJvbGUYAiABKAkSEAoIbXV0YXRpbmcYAyABKAgSDAoEbGVhZBgEIAEoCBIXCg9yb3V0ZWRfY2F0ZWdvcnkYBSABKAkSFAoMcm91dGVkX21vZGVsGAYgASgJEg0KBW1vZGVsGAcgASgJEhYKDnJvdXRpbmdfcmVhc29uGAggASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YCSABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESEAoIcHJvdmlkZXIYCiABKAkSIAoYZXhwbGljaXRfcm91dGVyX2NhdGVnb3J5GAsgASgJQhMKEV9yb3V0aW5nX2RlY2lzaW9uIvoDCgRUZWFtEhYKDnBhcmVudF9jYWxsX2lkGAEgASgJEg8KB3RlYW1faWQYAiABKAkSKQoGcm9zdGVyGAMgAygLMhkubWVjYXRsLnYxLlRlYW1NZW1iZXJTcGVjEg4KBm1lbWJlchgEIAEoCRISCgppbm5lcl9raW5kGAUgASgJEgwKBHRleHQYBiABKAkSEQoJdG9vbF9uYW1lGAcgASgJEg4KBmRldGFpbBgIIAEoCRIQCghpc19lcnJvchgJIAEoCBIOCgZyb3VuZHMYCiABKAUSDAoEc3RvcBgLIAEoCRIfCgV1c2FnZRgMIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIUCgxjb250ZXh0X3VzZWQYDSABKAMSFgoOY29udGV4dF93aW5kb3cYDiABKAMSIgoFdGFza3MYDyADKAsyEy5tZWNhdGwudjEuVGVhbVRhc2sSKAoIZmluZGluZ3MYECADKAsyFi5tZWNhdGwudjEuVGVhbUZpbmRpbmcSNgoMZGlzcG9zaXRpb25zGBEgAygLMiAubWVjYXRsLnYxLlRlYW1NZW1iZXJEaXNwb3NpdGlvbhIZChFtZW1iZXJfc2Vzc2lvbl9pZBgSIAEoCRINCgVjYXVzZRgTIAEoCRIaChJjaGlsZF90b29sX2NhbGxfaWQYFCABKAkijgUKCFBhcmFsbGVsEhYKDnBhcmVudF9jYWxsX2lkGAEgASgJEgwKBGtpbmQYAiABKAkSDAoEam9pbhgDIAEoCRIUCgxicmFuY2hfY291bnQYBCABKAUSFAoMYnJhbmNoX2luZGV4GAUgASgFEhQKDGJyYW5jaF9sYWJlbBgGIAEoCRIMCgRnb2FsGAcgASgJEhEKCXRvb2xfbmFtZRgIIAEoCRIQCghpc19lcnJvchgJIAEoCBISCgp0b29sX2NvdW50GAogASgFEg4KBmZhaWxlZBgLIAEoCBIMCgRzdG9wGA0gASgJEh8KBXVzYWdlGA4gASgLMhAubWVjYXRsLnYxLlVzYWdlEhMKC2R1cmF0aW9uX21zGA8gASgDEg4KBndpbm5lchgQIAEoBRIQCghjaGlsZF9pZBgSIAEoCRIXCg9yb3V0ZWRfY2F0ZWdvcnkYEyABKAkSFAoMcm91dGVkX21vZGVsGBQgASgJEg0KBW1vZGVsGBUgASgJEhIKCmlubmVyX2tpbmQYFiABKAkSDAoEdGV4dBgXIAEoCRIOCgZkZXRhaWwYGCABKAkSFgoOcm91dGluZ19yZWFzb24YGSABKAkSOQoQcm91dGluZ19kZWNpc2lvbhgaIAEoCzIaLm1lY2F0bC52MS5Sb3V0aW5nRGVjaXNpb25IAIgBARIaChJjaGlsZF90b29sX2NhbGxfaWQYGyABKAkSEAoIcHJvdmlkZXIYHCABKAkSIAoYZXhwbGljaXRfcm91dGVyX2NhdGVnb3J5GB0gASgJQhMKEV9yb3V0aW5nX2RlY2lzaW9uSgQIDBANSgQIERASUgl3b3Jrc3BhY2VSEHdpbm5lcl93b3Jrc3BhY2UiMgoIVG9vbENhbGwSCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRhcmdzGAMgASgJIoUBCgpUb29sUmVzdWx0Eg8KB2NhbGxfaWQYASABKAkSDwoHY29udGVudBgCIAEoCRIQCghpc19lcnJvchgDIAEoCBInCgZibG9ja3MYBCADKAsyFy5tZWNhdGwudjEuQ29udGVudEJsb2NrEhoKEnN0cnVjdHVyZWRfY29udGVudBgFIAEoCSKjAQoNUGVybWlzc2lvbkFzaxIOCgZhc2tfaWQYASABKAkSDAoEdG9vbBgCIAEoCRIMCgRhcmdzGAMgASgJEg4KBnJlYXNvbhgEIAEoCRI0CglndWFyZHJhaWwYBSABKAsyIS5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxTY29wZRIUCgdjYWxsX2lkGAYgASgJSACIAQFCCgoIX2NhbGxfaWQihQIKBlJlc3VsdBIMCgRzdG9wGAEgASgJEgwKBHRleHQYAiABKAkSHwoFdXNhZ2UYAyABKAsyEC5tZWNhdGwudjEuVXNhZ2USDQoFZXJyb3IYBCABKAkSOwoRcmV0cnlfZGlzcG9zaXRpb24YBiABKA4yGy5tZWNhdGwudjEuUmV0cnlEaXNwb3NpdGlvbkgAiAEBEjcKD3N0cmVhbV9wcm9ncmVzcxgHIAEoDjIZLm1lY2F0bC52MS5TdHJlYW1Qcm9ncmVzc0gBiAEBQhQKEl9yZXRyeV9kaXNwb3NpdGlvbkISChBfc3RyZWFtX3Byb2dyZXNzSgQIBRAGUglwZXJtYW5lbnQiUgoHVHVybkVuZBIfCgV1c2FnZRgBIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgCIAEoAxIRCgllc3RpbWF0ZWQYAyABKAgihQEKBVVzYWdlEhQKDGlucHV0X3Rva2VucxgBIAEoAxIVCg1vdXRwdXRfdG9rZW5zGAIgASgDEhkKEWNhY2hlX3JlYWRfdG9rZW5zGAMgASgDEhoKEmNhY2hlX3dyaXRlX3Rva2VucxgEIAEoAxIYChByZWFzb25pbmdfdG9rZW5zGAUgASgDIpABCgtNY3BSZXNvdXJjZRIOCgZzZXJ2ZXIYASABKAkSCwoDdXJpGAIgASgJEgwKBG5hbWUYAyABKAkSDQoFdGl0bGUYBCABKAkSEwoLZGVzY3JpcHRpb24YBSABKAkSEQoJbWltZV90eXBlGAYgASgJEgwKBHNpemUYByABKAMSEQoJcmVhZF9vbmx5GAggASgIIikKF0xpc3RNY3BSZXNvdXJjZXNSZXF1ZXN0Eg4KBnNlcnZlchgBIAEoCSJFChhMaXN0TWNwUmVzb3VyY2VzUmVzcG9uc2USKQoJcmVzb3VyY2VzGAEgAygLMhYubWVjYXRsLnYxLk1jcFJlc291cmNlIlEKE01jcFJlc291cmNlQ29udGVudHMSCwoDdXJpGAEgASgJEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgR0ZXh0GAMgASgJEgwKBGJsb2IYBCABKAwiRwoWUmVhZE1jcFJlc291cmNlUmVxdWVzdBIXCgZzZXJ2ZXIYASABKAlCB7pIBHICEAESFAoDdXJpGAIgASgJQge6SARyAhABIksKF1JlYWRNY3BSZXNvdXJjZVJlc3BvbnNlEjAKCGNvbnRlbnRzGAEgAygLMh4ubWVjYXRsLnYxLk1jcFJlc291cmNlQ29udGVudHMiVwoRTWNwUHJvbXB0QXJndW1lbnQSDAoEbmFtZRgBIAEoCRINCgV0aXRsZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRIQCghyZXF1aXJlZBgEIAEoCCJ+CglNY3BQcm9tcHQSDgoGc2VydmVyGAEgASgJEgwKBG5hbWUYAiABKAkSDQoFdGl0bGUYAyABKAkSEwoLZGVzY3JpcHRpb24YBCABKAkSLwoJYXJndW1lbnRzGAUgAygLMhwubWVjYXRsLnYxLk1jcFByb21wdEFyZ3VtZW50IicKFUxpc3RNY3BQcm9tcHRzUmVxdWVzdBIOCgZzZXJ2ZXIYASABKAkiPwoWTGlzdE1jcFByb21wdHNSZXNwb25zZRIlCgdwcm9tcHRzGAEgAygLMhQubWVjYXRsLnYxLk1jcFByb21wdCK5AQoTR2V0TWNwUHJvbXB0UmVxdWVzdBIXCgZzZXJ2ZXIYASABKAlCB7pIBHICEAESFQoEbmFtZRgCIAEoCUIHukgEcgIQARJACglhcmd1bWVudHMYAyADKAsyLS5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVxdWVzdC5Bcmd1bWVudHNFbnRyeRowCg5Bcmd1bWVudHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIi4KEE1jcFByb21wdE1lc3NhZ2USDAoEcm9sZRgBIAEoCRIMCgR0ZXh0GAIgASgJIloKFEdldE1jcFByb21wdFJlc3BvbnNlEhMKC2Rlc2NyaXB0aW9uGAEgASgJEi0KCG1lc3NhZ2VzGAIgAygLMhsubWVjYXRsLnYxLk1jcFByb21wdE1lc3NhZ2UiTAoNTWNwU2VydmVySW5mbxIMCgRuYW1lGAEgASgJEgsKA3VybBgCIAEoCRIRCgl0cmFuc3BvcnQYAyABKAkSDQoFZ3JvdXAYBCABKAkihwEKCU1jcFNvdXJjZRIMCgRuYW1lGAEgASgJEgwKBGtpbmQYAiABKAkSDwoHZW5hYmxlZBgDIAEoCBINCgVncm91cBgEIAEoCRIpCgdzZXJ2ZXJzGAUgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlckluZm8SEwoLZGlhZ25vc3RpY3MYBiADKAkiFwoVTGlzdE1jcFNvdXJjZXNSZXF1ZXN0InUKFkxpc3RNY3BTb3VyY2VzUmVzcG9uc2USJQoHc291cmNlcxgBIAMoCzIULm1lY2F0bC52MS5NY3BTb3VyY2USEAoIcmV2aXNpb24YAiABKAQSDQoFc3RhbGUYAyABKAgSEwoLcmVjb25jaWxpbmcYBCABKAgiNwoYUmVmcmVzaE1jcFNvdXJjZXNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiPgoZUmVmcmVzaE1jcFNvdXJjZXNSZXNwb25zZRIQCghyZXZpc2lvbhgBIAEoBBIPCgdjaGFuZ2VkGAIgASgIIhsKGUxpc3RUb29sSGl2ZUdyb3Vwc1JlcXVlc3QiLAoaTGlzdFRvb2xIaXZlR3JvdXBzUmVzcG9uc2USDgoGZ3JvdXBzGAEgAygJInQKCUFnZW50SW5mbxIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg0KBW1vZGVsGAMgASgJEg0KBXRvb2xzGAQgAygJEhcKD3Blcm1pc3Npb25fbW9kZRgFIAEoCRINCgVjb2xvchgGIAEoCSITChFMaXN0QWdlbnRzUmVxdWVzdCI6ChJMaXN0QWdlbnRzUmVzcG9uc2USJAoGYWdlbnRzGAEgAygLMhQubWVjYXRsLnYxLkFnZW50SW5mbyIsCgdDb21tYW5kEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkiMgoTTGlzdENvbW1hbmRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjwKFExpc3RDb21tYW5kc1Jlc3BvbnNlEiQKCGNvbW1hbmRzGAEgAygLMhIubWVjYXRsLnYxLkNvbW1hbmQiaQoIV29ya3RyZWUSEAoIc2VsZWN0b3IYASABKAkSDAoEa2luZBgCIAEoCRINCgVsYWJlbBgDIAEoCRIOCgZicmFuY2gYBCABKAkSEAoIcmV2aXNpb24YBSABKAkSDAoEYmFyZRgGIAEoCCIzChRMaXN0V29ya3RyZWVzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIj8KFUxpc3RXb3JrdHJlZXNSZXNwb25zZRImCgl3b3JrdHJlZXMYASADKAsyEy5tZWNhdGwudjEuV29ya3RyZWUicAoJU2tpbGxJbmZvEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEwoLYWdlbnRfb3duZWQYAyABKAgSEwoLb3duZXJfYWdlbnQYBCABKAkSFgoOYWN0aXZlX3ZlcnNpb24YBSABKAkiEwoRTGlzdFNraWxsc1JlcXVlc3QiOgoSTGlzdFNraWxsc1Jlc3BvbnNlEiQKBnNraWxscxgBIAMoCzIULm1lY2F0bC52MS5Ta2lsbEluZm8iQQoNU2tpbGxGaWxlSW5mbxIMCgRuYW1lGAEgASgJEgwKBHNpemUYAiABKAMSFAoMaW5zdHJ1Y3Rpb25zGAMgASgIIi4KFUxpc3RTa2lsbEZpbGVzUmVxdWVzdBIVCgRuYW1lGAEgASgJQge6SARyAhABIkEKFkxpc3RTa2lsbEZpbGVzUmVzcG9uc2USJwoFZmlsZXMYASADKAsyGC5tZWNhdGwudjEuU2tpbGxGaWxlSW5mbyJEChRSZWFkU2tpbGxGaWxlUmVxdWVzdBIVCgRuYW1lGAEgASgJQge6SARyAhABEhUKBGZpbGUYAiABKAlCB7pIBHICEAEiKAoVUmVhZFNraWxsRmlsZVJlc3BvbnNlEg8KB2NvbnRlbnQYASABKAkioQEKCFNvdWxJbmZvEg8KB2NvbnRlbnQYASABKAkSEgoKc2l6ZV9ieXRlcxgCIAEoAxIOCgZzaGEyNTYYAyABKAkSDwoHcHJlc2VudBgEIAEoCBItCgpwcm92ZW5hbmNlGAUgASgOMhkubWVjYXRsLnYxLlNvdWxQcm92ZW5hbmNlEg8KB3RydXN0ZWQYBiABKAgSDwoHZHJpZnRlZBgHIAEoCCIQCg5HZXRTb3VsUmVxdWVzdCI0Cg9HZXRTb3VsUmVzcG9uc2USIQoEc291bBgBIAEoCzITLm1lY2F0bC52MS5Tb3VsSW5mbyIyCg5Vc2VyTW9kZWxFbnRyeRILCgNrZXkYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkiIgoTR2V0VXNlck1vZGVsUmVxdWVzdBILCgNrZXkYASABKAkilgIKEVVzZXJNb2RlbFJldmlzaW9uEgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRIPCgd2ZXJzaW9uGAQgASgJEg4KBnN0YXR1cxgFIAEoCRIOCgZ3cml0ZXIYBiABKAkSDgoGb3JpZ2luGAcgASgJEhkKEXNvdXJjZV9zZXNzaW9uX2lkGAggASgJEhoKEnNvdXJjZV9wcm9wb3NhbF9pZBgJIAEoCRIuCgp1cGRhdGVkX2F0GAsgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEoECAoQC1IPc291cmNlX2V2ZW50X2lkUhFzb3VyY2VfbWVzc2FnZV9pZCKKAQoPVXNlck1vZGVsRGV0YWlsEi0KB2N1cnJlbnQYASABKAsyHC5tZWNhdGwudjEuVXNlck1vZGVsUmV2aXNpb24SLQoHaGlzdG9yeRgCIAMoCzIcLm1lY2F0bC52MS5Vc2VyTW9kZWxSZXZpc2lvbhIZChFoaXN0b3J5X2F2YWlsYWJsZRgDIAEoCCKSAQoUR2V0VXNlck1vZGVsUmVzcG9uc2USKgoHZW50cmllcxgBIAMoCzIZLm1lY2F0bC52MS5Vc2VyTW9kZWxFbnRyeRISCgpzaXplX2J5dGVzGAIgASgDEg4KBnNoYTI1NhgDIAEoCRIqCgZkZXRhaWwYBCABKAsyGi5tZWNhdGwudjEuVXNlck1vZGVsRGV0YWlsIpIBCglNb2RlbEluZm8SCgoCaWQYASABKAkSEwoLcHJvdmlkZXJfaWQYAiABKAkSFAoMZGlzcGxheV9uYW1lGAMgASgJEg0KBWltYWdlGAQgASgIEhEKCXJlYXNvbmluZxgFIAEoCBIVCg1jb250ZXh0X2xpbWl0GAYgASgDEhUKDXByb21wdF9jYWNoZWQYByABKAgiEwoRTGlzdE1vZGVsc1JlcXVlc3QimwEKDlByb3ZpZGVyU3RhdHVzEhMKC3Byb3ZpZGVyX2lkGAEgASgJEg0KBXN0YXRlGAIgASgJEgwKBGhpbnQYAyABKAkSIwobZGVmYXVsdF9tb2RlbF9hdXRvX3NlbGVjdGVkGAQgASgIEhMKC21vZGVsX2NvdW50GAUgASgFEh0KFWF2YWlsYWJsZV9ub3RfZGVmYXVsdBgGIAEoCCJuChJMaXN0TW9kZWxzUmVzcG9uc2USJAoGbW9kZWxzGAEgAygLMhQubWVjYXRsLnYxLk1vZGVsSW5mbxIyCg9wcm92aWRlcl9zdGF0dXMYAiADKAsyGS5tZWNhdGwudjEuUHJvdmlkZXJTdGF0dXMiQQoVUmVmbGVjdFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAFKBAgCEANSBWFzeW5jIrkBChFSZWZsZWN0aW9uUmVjZWlwdBIVCg1yZWZsZWN0aW9uX2lkGAEgASgJEhMKC2Rpc3Bvc2l0aW9uGAIgASgJEg4KBnF1ZXVlZBgDIAEoBRIRCglhYnN0YWluZWQYBCABKAgSDgoGc3RhZ2VkGAUgASgFEhAKCHByb21vdGVkGAYgASgFEhIKCmNvbmZsaWN0ZWQYByABKAUSDgoGcmVhc29uGAggASgJEg8KB21lc3NhZ2UYCSABKAkiRwoWUmVmbGVjdFNlc3Npb25SZXNwb25zZRItCgdyZWNlaXB0GAEgASgLMhwubWVjYXRsLnYxLlJlZmxlY3Rpb25SZWNlaXB0IvECCg9MZWFybmluZ0F0dGVtcHQSCgoCaWQYASABKAkSDwoHdmVyc2lvbhgCIAEoCRINCgVzdGF0ZRgDIAEoCRIPCgdvdXRjb21lGAQgASgJEhQKDGZhaWx1cmVfY29kZRgFIAEoCRIaChJhdHRlbXB0X2dlbmVyYXRpb24YBiABKAQSGAoQY2xhaW1fZ2VuZXJhdGlvbhgHIAEoBBI0ChBjbGFpbV9leHBpcmVzX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIYChBjaGVja3BvaW50X3N0YWdlGAkgASgJEhMKC3Byb3Bvc2FsX2lkGAogASgJEhAKCHNraWxsX2lkGAsgASgJEi4KCmNyZWF0ZWRfYXQYDCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYDSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIjAKGUdldExlYXJuaW5nQXR0ZW1wdFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAEiSQoaR2V0TGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USKwoHYXR0ZW1wdBgBIAEoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQiSwobTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXF1ZXN0Eg0KBXN0YXRlGAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBSJhChxMaXN0TGVhcm5pbmdBdHRlbXB0c1Jlc3BvbnNlEiwKCGF0dGVtcHRzGAEgAygLMhoubWVjYXRsLnYxLkxlYXJuaW5nQXR0ZW1wdBITCgtuZXh0X2N1cnNvchgCIAEoCSJWChxNdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEiEKEGV4cGVjdGVkX3ZlcnNpb24YAiABKAlCB7pIBHICEAEiTAodTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USKwoHYXR0ZW1wdBgBIAEoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQiXgocTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVxdWVzdBIOCgZzdGF0dXMYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFEg8KB3Byb2plY3QYBCABKAkivgEKE0xlYXJuaW5nRXZpZGVuY2VSZWYSEgoKc2Vzc2lvbl9pZBgBIAEoCRIPCgdsb2NhdG9yGAIgASgJEg8KB29yZGluYWwYAyABKAUSEQoJZXZlbnRfc2VxGAQgASgDEhQKDHRvb2xfY2FsbF9pZBgFIAEoCRIOCgZkaWdlc3QYBiABKAkSEQoJYXZhaWxhYmxlGAcgASgIEhQKDGF2YWlsYWJpbGl0eRgIIAEoCRIPCgdwcmV2aWV3GAkgASgJImcKEExlYXJuaW5nRGVjaXNpb24SDAoEa2luZBgBIAEoCRINCgVhY3RvchgCIAEoCRIOCgZyZWFzb24YAyABKAkSJgoCYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wInkKGExlYXJuaW5nUHJvbW90aW9uUmVjZWlwdBISCgptZW1vcnlfa2V5GAEgASgJEhcKD3ByZXZpb3VzX2V4aXN0cxgCIAEoCBIYChBwcmV2aW91c192ZXJzaW9uGAMgASgJEhYKDnJlc3VsdF92ZXJzaW9uGAQgASgJIpwEChBMZWFybmluZ1Byb3Bvc2FsEgoKAmlkGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSDgoGc3RhdHVzGAMgASgJEgwKBGtpbmQYBCABKAkSCwoDa2V5GAUgASgJEg0KBXZhbHVlGAYgASgJEhMKC2Rlc2NyaXB0aW9uGAcgASgJEg0KBXRpdGxlGAggASgJEgwKBGJvZHkYCSABKAkSMAoIZXZpZGVuY2UYCiADKAsyHi5tZWNhdGwudjEuTGVhcm5pbmdFdmlkZW5jZVJlZhIQCgh0cmlnZ2VycxgLIAMoCRIuCglkZWNpc2lvbnMYDCADKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdEZWNpc2lvbhI2Cglwcm9tb3Rpb24YDSABKAsyIy5tZWNhdGwudjEuTGVhcm5pbmdQcm9tb3Rpb25SZWNlaXB0Ei4KCmNyZWF0ZWRfYXQYDiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhYKDnByb2plY3Rfc2NvcGVkGBAgASgIEhsKE3Byb21vdGlvbl9hdmFpbGFibGUYESABKAgSJAoccHJvbW90aW9uX3VuYXZhaWxhYmxlX3JlYXNvbhgSIAEoCRIYChBsZWFybmVkX3NraWxsX2lkGBMgASgJImQKHUxpc3RMZWFybmluZ1Byb3Bvc2Fsc1Jlc3BvbnNlEi4KCXByb3Bvc2FscxgBIAMoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsEhMKC25leHRfY3Vyc29yGAIgASgJIkIKGkdldExlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEg8KB3Byb2plY3QYAiABKAkiTAobR2V0TGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwikwEKHURlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEiEKEGV4cGVjdGVkX3ZlcnNpb24YAiABKAlCB7pIBHICEAESGQoIZGVjaXNpb24YAyABKAlCB7pIBHICEAESDgoGcmVhc29uGAQgASgJEg8KB3Byb2plY3QYBSABKAkiTwoeRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwiZwocVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABEg8KB3Byb2plY3QYAyABKAkiTgodVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVzcG9uc2USLQoIcHJvcG9zYWwYASABKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbCLsAwoTTGVhcm5lZFNraWxsVmVyc2lvbhIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSEAoIcmV2aXNpb24YBCABKAkSDQoFc3RhdGUYBSABKAkSEwoLb3duZXJfYWdlbnQYBiABKAkSEwoLZGVzY3JpcHRpb24YByABKAkSDAoEYm9keRgIIAEoCRISCgpzdXBlcnNlZGVzGAkgASgJEhYKDmV2aWRlbmNlX2NvdW50GAogASgFEjAKCGV2aWRlbmNlGAsgAygLMh4ubWVjYXRsLnYxLkxlYXJuaW5nRXZpZGVuY2VSZWYSLwoLZXZhbHVhdGlvbnMYDCADKAsyGi5tZWNhdGwudjEuU2tpbGxFdmFsdWF0aW9uEi8KCHJlY2VpcHRzGA0gAygLMh0ubWVjYXRsLnYxLlNraWxsQ2hhbmdlUmVjZWlwdBIuCgpjcmVhdGVkX2F0GA4gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIZChFpbnNwZWN0X2F2YWlsYWJsZRgQIAEoCBIWCg51bmRvX2F2YWlsYWJsZRgRIAEoCCKUAQoPU2tpbGxFdmFsdWF0aW9uEg8KB3ZlcmRpY3QYASABKAkSEwoLZml4dHVyZV9pZHMYAiADKAkSEAoIYmFzZWxpbmUYAyABKAkSEQoJdHJlYXRtZW50GAQgASgJEg4KBnJlYXNvbhgFIAEoCRImCgJhdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiggMKElNraWxsQ2hhbmdlUmVjZWlwdBIKCgJpZBgBIAEoCRIQCghza2lsbF9pZBgCIAEoCRIMCgRuYW1lGAMgASgJEg8KB3ZlcnNpb24YBCABKAkSEQoJb3BlcmF0aW9uGAUgASgJEhIKCmZyb21fc3RhdGUYBiABKAkSEAoIdG9fc3RhdGUYByABKAkSFgoOZXZpZGVuY2VfY291bnQYCCABKAUSGgoSc291cmNlX3Nlc3Npb25faWRzGAkgAygJEhwKFHNvdXJjZV90b29sX2NhbGxfaWRzGAogAygJEg8KB3ZlcmRpY3QYCyABKAkSEwoLZml4dHVyZV9pZHMYDCADKAkSEAoIYmFzZWxpbmUYDSABKAkSEQoJdHJlYXRtZW50GA4gASgJEiYKAmF0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIZChFpbnNwZWN0X2F2YWlsYWJsZRgQIAEoCBIWCg51bmRvX2F2YWlsYWJsZRgRIAEoCCJuChhMaXN0TGVhcm5lZFNraWxsc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUSDQoFc3RhdGUYBCABKAkSEwoLb3duZXJfYWdlbnQYBSABKAkihQEKGUxpc3RMZWFybmVkU2tpbGxzUmVzcG9uc2USLgoGc2tpbGxzGAEgAygLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEwoLbmV4dF9jdXJzb3IYAiABKAkSEgoKZ2VuZXJhdGlvbhgDIAEoBBIPCgdwcm9qZWN0GAQgASgJIm0KFkdldExlYXJuZWRTa2lsbFJlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIPCgd2ZXJzaW9uGAQgASgJIm0KF0dldExlYXJuZWRTa2lsbFJlc3BvbnNlEi0KBXNraWxsGAEgASgLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJIqEBCh9EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESHQoMZnJvbV92ZXJzaW9uGAQgASgJQge6SARyAhABEhsKCnRvX3ZlcnNpb24YBSABKAlCB7pIBHICEAEikQEKIERpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1Jlc3BvbnNlEgwKBGRpZmYYASABKAkSEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJEhAKCHNraWxsX2lkGAQgASgJEhQKDGZyb21fdmVyc2lvbhgFIAEoCRISCgp0b192ZXJzaW9uGAYgASgJIp0BChlNdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESGAoHdmVyc2lvbhgEIAEoCUIHukgEcgIQARIiChFleHBlY3RlZF9yZXZpc2lvbhgFIAEoCUIHukgEcgIQASKnAQoaTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USLQoFc2tpbGwYASABKAsyHi5tZWNhdGwudjEuTGVhcm5lZFNraWxsVmVyc2lvbhISCgpnZW5lcmF0aW9uGAIgASgEEg8KB3Byb2plY3QYAyABKAkSGgoScHVibGljYXRpb25fc3RhdHVzGAQgASgJEhkKEXB1YmxpY2F0aW9uX2Vycm9yGAUgASgJIqYBChtSb2xsYmFja0xlYXJuZWRTa2lsbFJlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIfCg50YXJnZXRfdmVyc2lvbhgEIAEoCUIHukgEcgIQARIiChFleHBlY3RlZF9yZXZpc2lvbhgFIAEoCUIHukgEcgIQASJJChdMaXN0U2tpbGxDaGFuZ2VzUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBSKEAQoYTGlzdFNraWxsQ2hhbmdlc1Jlc3BvbnNlEi4KB2NoYW5nZXMYASADKAsyHS5tZWNhdGwudjEuU2tpbGxDaGFuZ2VSZWNlaXB0EhMKC25leHRfY3Vyc29yGAIgASgJEhIKCmdlbmVyYXRpb24YAyABKAQSDwoHcHJvamVjdBgEIAEoCSKPAQoRQ3JlYXRlVGVhbVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIMCgRuYW1lGAIgASgJEigKB21lbWJlcnMYAyADKAsyFy5tZWNhdGwudjEuVGVhbW1hdGVTcGVjEgwKBGdvYWwYBCABKAkSFwoPbWF4X3RlYW1fdG9rZW5zGAUgASgFIk0KEkNyZWF0ZVRlYW1SZXNwb25zZRIPCgd0ZWFtX2lkGAEgASgJEiYKB21lbWJlcnMYAiADKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlciJxCgxUZWFtbWF0ZVNwZWMSFQoEbmFtZRgBIAEoCUIHukgEcgIQARISCgphZ2VudF90eXBlGAIgASgJEgwKBGxlYWQYAyABKAgSEAoIbXV0YXRpbmcYBCABKAgSFgoOaW5pdGlhbF9wcm9tcHQYBSABKAkikwEKFFNwYXduVGVhbW1hdGVSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESFQoEbmFtZRgCIAEoCUIHukgEcgIQARISCgphZ2VudF90eXBlGAMgASgJEgwKBGxlYWQYBCABKAgSEAoIbXV0YXRpbmcYBSABKAgSFgoOaW5pdGlhbF9wcm9tcHQYBiABKAkiPgoVU3Bhd25UZWFtbWF0ZVJlc3BvbnNlEiUKBm1lbWJlchgBIAEoCzIVLm1lY2F0bC52MS5UZWFtTWVtYmVyInAKGlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESEwoCdG8YAiABKAlCB7pIBHICEAESDAoEZnJvbRgDIAEoCRIVCgRib2R5GAQgASgJQge6SARyAhABIh0KG1NlbmRUZWFtbWF0ZU1lc3NhZ2VSZXNwb25zZSJKChVDYW5jZWxUZWFtbWF0ZVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQARIXCgZtZW1iZXIYAiABKAlCB7pIBHICEAEiGAoWQ2FuY2VsVGVhbW1hdGVSZXNwb25zZSIqCg5SdW5UZWFtUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABImUKCVRlYW1FdmVudBIOCgZtZW1iZXIYASABKAkSHwoFZXZlbnQYAiABKAsyEC5tZWNhdGwudjEuRXZlbnQSJwoHb3V0Y29tZRgDIAEoCzIWLm1lY2F0bC52MS5UZWFtT3V0Y29tZSLbAQoLVGVhbU91dGNvbWUSDgoGcm91bmRzGAEgASgFEhEKCXF1aWVzY2VudBgCIAEoCBIYChBidWRnZXRfZXhoYXVzdGVkGAMgASgIEgwKBHN0b3AYBCABKAkSHwoFdXNhZ2UYBSABKAsyEC5tZWNhdGwudjEuVXNhZ2USNgoMZGlzcG9zaXRpb25zGAYgAygLMiAubWVjYXRsLnYxLlRlYW1NZW1iZXJEaXNwb3NpdGlvbhIoCghmaW5kaW5ncxgHIAMoCzIWLm1lY2F0bC52MS5UZWFtRmluZGluZyIrCg9MaXN0VGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASJxChBMaXN0VGVhbVJlc3BvbnNlEiYKB21lbWJlcnMYASADKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlchIiCgV0YXNrcxgCIAMoCzITLm1lY2F0bC52MS5UZWFtVGFzaxIRCglxdWllc2NlbnQYAyABKAgiUQoKVGVhbU1lbWJlchIMCgRuYW1lGAEgASgJEhIKCmFnZW50X3R5cGUYAiABKAkSDQoFc3RhdGUYAyABKAkSEgoKc2Vzc2lvbl9pZBgEIAEoCSJaCghUZWFtVGFzaxIKCgJpZBgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVzdGF0ZRgDIAEoCRIQCghhc3NpZ25lZRgEIAEoCRIMCgRkZXBzGAUgAygJIisKC1RlYW1GaW5kaW5nEg4KBm1lbWJlchgBIAEoCRIMCgRib2R5GAIgASgJIn0KFVRlYW1NZW1iZXJEaXNwb3NpdGlvbhIMCgRuYW1lGAEgASgJEg8KB3N0b3BwZWQYAiABKAgSLwoGcmVhc29uGAMgASgOMh8ubWVjYXRsLnYxLlRlYW1NZW1iZXJTdG9wUmVhc29uEhQKDGVycm9yX3JvdW5kcxgEIAEoBSIuChJDbGVhbnVwVGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASIVChNDbGVhbnVwVGVhbVJlc3BvbnNlIm8KEkFwcHJvdmVQbGFuUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEi4KC3RhcmdldF9tb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEgwKBG5vdGUYAyABKAkiiQEKF01hbnVhbERyZWFtQ2FwYWJpbGl0aWVzEjgKDnByb2plY3RfbWVtb3J5GAEgASgLMiAubWVjYXRsLnYxLkRyZWFtVGFyZ2V0Q2FwYWJpbGl0eRI0Cgp1c2VyX21vZGVsGAIgASgLMiAubWVjYXRsLnYxLkRyZWFtVGFyZ2V0Q2FwYWJpbGl0eSJVChVEcmVhbVRhcmdldENhcGFiaWxpdHkSEAoIZ2VuZXJhdGUYASABKAgSDgoGZGVjaWRlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCSIqChhHZW5lcmF0ZURyZWFtUGxhblJlcXVlc3QSDgoGdGFyZ2V0GAEgASgJIkUKGUdlbmVyYXRlRHJlYW1QbGFuUmVzcG9uc2USKAoEcGxhbhgBIAEoCzIaLm1lY2F0bC52MS5EcmVhbVJldmlld1BsYW4iOwoWRGVjaWRlRHJlYW1QbGFuUmVxdWVzdBIPCgdwbGFuX2lkGAEgASgJEhAKCGRlY2lzaW9uGAIgASgJIkMKF0RlY2lkZURyZWFtUGxhblJlc3BvbnNlEigKB3JlY2VpcHQYASABKAsyFy5tZWNhdGwudjEuRHJlYW1SZWNlaXB0IssBCg9EcmVhbVJldmlld1BsYW4SCgoCaWQYASABKAkSDgoGdGFyZ2V0GAIgASgJEi4KCmV4cGlyZXNfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEh8KF3BsYW5uZWRfb3BlcmF0aW9uX2NvdW50GAQgASgFEhwKFHBsYW5uZWRfc291cmNlX2NvdW50GAUgASgFEi0KCm9wZXJhdGlvbnMYBiADKAsyGS5tZWNhdGwudjEuRHJlYW1PcGVyYXRpb24i3wEKDkRyZWFtT3BlcmF0aW9uEgwKBGtpbmQYASABKAkSLQoIc3Vydml2b3IYAiABKAsyGy5tZWNhdGwudjEuRHJlYW1QYXJ0aWNpcGFudBIsCgdzb3VyY2VzGAMgAygLMhsubWVjYXRsLnYxLkRyZWFtUGFydGljaXBhbnQSMAoLcmVwbGFjZW1lbnQYBCABKAsyGy5tZWNhdGwudjEuRHJlYW1SZXBsYWNlbWVudBIOCgZyZWFzb24YBSABKAkSIAoYZXhhY3RfZHVwbGljYXRlX2VsaWdpYmxlGAYgASgIIkMKEERyZWFtUGFydGljaXBhbnQSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJIjYKEERyZWFtUmVwbGFjZW1lbnQSDQoFdmFsdWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAki1wEKDERyZWFtUmVjZWlwdBIKCgJpZBgBIAEoCRIOCgZ0YXJnZXQYAiABKAkSEwoLZGlzcG9zaXRpb24YAyABKAkSHAoUcGxhbm5lZF9zb3VyY2VfY291bnQYBCABKAUSHAoUYXBwbGllZF9zb3VyY2VfY291bnQYBSABKAUSHwoXY29uZmxpY3RlZF9zb3VyY2VfY291bnQYBiABKAUSHAoUc2tpcHBlZF9zb3VyY2VfY291bnQYByABKAUSGwoTZmFpbGVkX3NvdXJjZV9jb3VudBgIIAEoBSI0ChVDb21wYWN0U2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASIrChZDb21wYWN0U2Vzc2lvblJlc3BvbnNlEhEKCWNvbXBhY3RlZBgBIAEoCCI3CiFXb3Jrc3BhY2VFbnJvbGxtZW50Q29ubmVjdFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCSJOCiFXb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIVCg1lbnJvbGxtZW50X2lkGAIgASgJInEKE1dvcmtzcGFjZUVucm9sbG1lbnQSFQoNZW5yb2xsbWVudF9pZBgBIAEoCRIOCgZzdGF0dXMYAiABKAkSGQoRcmVxdWlyZWRfc2VydmljZXMYAyABKA0SGAoQcHJlc2VudGF0aW9uX3VybBgEIAEoCSq+AQoOUGVybWlzc2lvbk1vZGUSHwobUEVSTUlTU0lPTl9NT0RFX1VOU1BFQ0lGSUVEEAASGwoXUEVSTUlTU0lPTl9NT0RFX0RFRkFVTFQQARIYChRQRVJNSVNTSU9OX01PREVfUExBThACEiAKHFBFUk1JU1NJT05fTU9ERV9BQ0NFUFRfRURJVFMQAxIYChRQRVJNSVNTSU9OX01PREVfQVVUTxAEEhgKFFBFUk1JU1NJT05fTU9ERV9ZT0xPEAUqkgEKD0FwcHJvdmFsVmVyZGljdBIgChxBUFBST1ZBTF9WRVJESUNUX1VOU1BFQ0lGSUVEEAASGQoVQVBQUk9WQUxfVkVSRElDVF9ERU5ZEAESHwobQVBQUk9WQUxfVkVSRElDVF9BTExPV19PTkNFEAISIQodQVBQUk9WQUxfVkVSRElDVF9BTExPV19BTFdBWVMQAyq+AQoMU3RlZXJPdXRjb21lEh0KGVNURUVSX09VVENPTUVfVU5TUEVDSUZJRUQQABIaChZTVEVFUl9PVVRDT01FX0FDQ0VQVEVEEAESGgoWU1RFRVJfT1VUQ09NRV9BUFBFTkRFRBACEhsKF1NURUVSX09VVENPTUVfUkVUUkFDVEVEEAMSHgoaU1RFRVJfT1VUQ09NRV9OT05FX1BFTkRJTkcQBBIaChZTVEVFUl9PVVRDT01FX1RPT19MQVRFEAUqgAEKDEd1YXJkcmFpbEpvYhIdChlHVUFSRFJBSUxfSk9CX1VOU1BFQ0lGSUVEEAASGAoUR1VBUkRSQUlMX0pPQl9BQ1RJT04QARIZChVHVUFSRFJBSUxfSk9CX0lOQk9VTkQQAhIcChhHVUFSRFJBSUxfSk9CX1BFUk1JU1NJT04QAyqqAQoTR3VhcmRyYWlsQXNzZXNzbWVudBIkCiBHVUFSRFJBSUxfQVNTRVNTTUVOVF9VTlNQRUNJRklFRBAAEiMKH0dVQVJEUkFJTF9BU1NFU1NNRU5UX0FDQ0VQVEFCTEUQARIjCh9HVUFSRFJBSUxfQVNTRVNTTUVOVF9QUk9ISUJJVEVEEAISIwofR1VBUkRSQUlMX0FTU0VTU01FTlRfVU5SRVNPTFZFRBADKowBChNHdWFyZHJhaWxJbnNwZWN0aW9uEiQKIEdVQVJEUkFJTF9JTlNQRUNUSU9OX1VOU1BFQ0lGSUVEEAASIQodR1VBUkRSQUlMX0lOU1BFQ1RJT05fQ09NUExFVEUQARIsCihHVUFSRFJBSUxfSU5TUEVDVElPTl9PUEVSQVRJT05BTF9GQUlMVVJFEAIq0AIKFEd1YXJkcmFpbERpc3Bvc2l0aW9uEiUKIUdVQVJEUkFJTF9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEiEKHUdVQVJEUkFJTF9ESVNQT1NJVElPTl9FWEVDVVRFEAESJAogR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0FTS19BQ1RJT04QAhIpCiVHVUFSRFJBSUxfRElTUE9TSVRJT05fV0lUSEhPTERfUkVTVUxUEAMSKAokR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1JFTEVBU0VfUkVTVUxUEAQSHgoaR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0RFTlkQBRInCiNHVUFSRFJBSUxfRElTUE9TSVRJT05fUEFTU19BRFZJU09SWRAGEioKJkdVQVJEUkFJTF9ESVNQT1NJVElPTl9DT05USU5VRV9XQVJOSU5HEAcqkAEKFUd1YXJkcmFpbEFwcHJvdmFsS2luZBInCiNHVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9VTlNQRUNJRklFRBAAEiIKHkdVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX0FDVElPThABEioKJkdVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX1JFU1VMVF9SRUxFQVNFEAIqmAEKDEhvb2tEZWNpc2lvbhIdChlIT09LX0RFQ0lTSU9OX1VOU1BFQ0lGSUVEEAASFgoSSE9PS19ERUNJU0lPTl9JTkZPEAESGQoVSE9PS19ERUNJU0lPTl9CTE9DS0VEEAISGgoWSE9PS19ERUNJU0lPTl9NT0RJRklFRBADEhoKFkhPT0tfREVDSVNJT05fQURWSVNPUlkQBCqWAQoQUmV0cnlEaXNwb3NpdGlvbhIhCh1SRVRSWV9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEh0KGVJFVFJZX0RJU1BPU0lUSU9OX1VOS05PV04QARIfChtSRVRSWV9ESVNQT1NJVElPTl9SRVRSWUFCTEUQAhIfChtSRVRSWV9ESVNQT1NJVElPTl9QRVJNQU5FTlQQAyqoAQoOU3RyZWFtUHJvZ3Jlc3MSHwobU1RSRUFNX1BST0dSRVNTX1VOU1BFQ0lGSUVEEAASGwoXU1RSRUFNX1BST0dSRVNTX1VOS05PV04QARIdChlTVFJFQU1fUFJPR1JFU1NfUFJFQ09NTUlUEAISGwoXU1RSRUFNX1BST0dSRVNTX1ZJU0lCTEUQAxIcChhTVFJFQU1fUFJPR1JFU1NfQ09NUExFVEUQBCqEAQoOU291bFByb3ZlbmFuY2USHwobU09VTF9QUk9WRU5BTkNFX1VOU1BFQ0lGSUVEEAASGAoUU09VTF9QUk9WRU5BTkNFX1VTRVIQARIbChdTT1VMX1BST1ZFTkFOQ0VfUFJPSkVDVBACEhoKFlNPVUxfUFJPVkVOQU5DRV9EUklWRVIQAyqtAQoUVGVhbU1lbWJlclN0b3BSZWFzb24SJwojVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fVU5TUEVDSUZJRUQQABIhCh1URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9FUlJPUhABEiUKIVRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0NBTkNFTExFRBACEiIKHlRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0JVREdFVBADMpw5Cg5IYXJuZXNzU2VydmljZRJnChRHZXRDb21wYXRpYmlsaXR5SW5mbxImLm1lY2F0bC52MS5HZXRDb21wYXRpYmlsaXR5SW5mb1JlcXVlc3QaJy5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXNwb25zZRJtChZMaXN0RXhlY3V0aW9uVGVtcGxhdGVzEigubWVjYXRsLnYxLkxpc3RFeGVjdXRpb25UZW1wbGF0ZXNSZXF1ZXN0GikubWVjYXRsLnYxLkxpc3RFeGVjdXRpb25UZW1wbGF0ZXNSZXNwb25zZRJSCg1DcmVhdGVTZXNzaW9uEh8ubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXNwb25zZRJSCg1HZXRTZXJ2ZXJJbmZvEh8ubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXF1ZXN0GiAubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXNwb25zZRJJCgpHZXRTZXNzaW9uEhwubWVjYXRsLnYxLkdldFNlc3Npb25SZXF1ZXN0Gh0ubWVjYXRsLnYxLkdldFNlc3Npb25SZXNwb25zZRJqChVMaXN0R3VhcmRyYWlsQ292ZXJhZ2USJy5tZWNhdGwudjEuTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVxdWVzdBooLm1lY2F0bC52MS5MaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXNwb25zZRJzChhHZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWwSKi5tZWNhdGwudjEuR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVxdWVzdBorLm1lY2F0bC52MS5HZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXNwb25zZRJnChRHZXRTZXNzaW9uVHJhbnNjcmlwdBImLm1lY2F0bC52MS5HZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QaJy5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRJACgdTZXRNb2RlEhkubWVjYXRsLnYxLlNldE1vZGVSZXF1ZXN0GhoubWVjYXRsLnYxLlNldE1vZGVSZXNwb25zZRJPCgxDbG9zZVNlc3Npb24SHi5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbG9zZVNlc3Npb25SZXNwb25zZRJSCg1SZW5hbWVTZXNzaW9uEh8ubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXNwb25zZRJSCg1EZWxldGVTZXNzaW9uEh8ubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXNwb25zZRJVCg5Db21wYWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5Db21wYWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXNwb25zZRJPCgxDbGVhclNlc3Npb24SHi5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbGVhclNlc3Npb25SZXNwb25zZRJMCgtGb3JrU2Vzc2lvbhIdLm1lY2F0bC52MS5Gb3JrU2Vzc2lvblJlcXVlc3QaHi5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXNwb25zZRJHCghDb252ZXJzZRIaLm1lY2F0bC52MS5Db252ZXJzZVJlcXVlc3QaGy5tZWNhdGwudjEuQ29udmVyc2VSZXNwb25zZSgBMAESUgoNUmVzb2x2ZVJ1bkFzaxIfLm1lY2F0bC52MS5SZXNvbHZlUnVuQXNrUmVxdWVzdBogLm1lY2F0bC52MS5SZXNvbHZlUnVuQXNrUmVzcG9uc2USVQoOUmVzb2x2ZVBsYW5Bc2sSIC5tZWNhdGwudjEuUmVzb2x2ZVBsYW5Bc2tSZXF1ZXN0GiEubWVjYXRsLnYxLlJlc29sdmVQbGFuQXNrUmVzcG9uc2USRgoJQ2FuY2VsUnVuEhsubWVjYXRsLnYxLkNhbmNlbFJ1blJlcXVlc3QaHC5tZWNhdGwudjEuQ2FuY2VsUnVuUmVzcG9uc2USQwoIU3RlZXJSdW4SGi5tZWNhdGwudjEuU3RlZXJSdW5SZXF1ZXN0GhsubWVjYXRsLnYxLlN0ZWVyUnVuUmVzcG9uc2USVQoOQ2FuY2VsUnVuU3RlZXISIC5tZWNhdGwudjEuQ2FuY2VsUnVuU3RlZXJSZXF1ZXN0GiEubWVjYXRsLnYxLkNhbmNlbFJ1blN0ZWVyUmVzcG9uc2USWwoQTGlzdE1jcFJlc291cmNlcxIiLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVzcG9uc2USWAoPUmVhZE1jcFJlc291cmNlEiEubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QaIi5tZWNhdGwudjEuUmVhZE1jcFJlc291cmNlUmVzcG9uc2USVQoOTGlzdE1jcFByb21wdHMSIC5tZWNhdGwudjEuTGlzdE1jcFByb21wdHNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USTwoMR2V0TWNwUHJvbXB0Eh4ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QaHy5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVzcG9uc2USVQoOTGlzdE1jcFNvdXJjZXMSIC5tZWNhdGwudjEuTGlzdE1jcFNvdXJjZXNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVzcG9uc2USXgoRUmVmcmVzaE1jcFNvdXJjZXMSIy5tZWNhdGwudjEuUmVmcmVzaE1jcFNvdXJjZXNSZXF1ZXN0GiQubWVjYXRsLnYxLlJlZnJlc2hNY3BTb3VyY2VzUmVzcG9uc2UScwoYTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzEioubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1JlcXVlc3QaKy5tZWNhdGwudjEuTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVzcG9uc2USYQoSTGlzdFRvb2xIaXZlR3JvdXBzEiQubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1JlcXVlc3QaJS5tZWNhdGwudjEuTGlzdFRvb2xIaXZlR3JvdXBzUmVzcG9uc2USSQoKTGlzdEFnZW50cxIcLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVzcG9uc2USTwoMTGlzdENvbW1hbmRzEh4ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdENvbW1hbmRzUmVzcG9uc2USUgoNTGlzdFdvcmt0cmVlcxIfLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVxdWVzdBogLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVzcG9uc2USUAoTU3RyZWFtU2Vzc2lvbkV2ZW50cxIlLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEkwKEVN0cmVhbVNlc3Npb25MaXZlEiMubWVjYXRsLnYxLlN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmMKEldhdGNoU2Vzc2lvbkV2ZW50cxIkLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0GiUubWVjYXRsLnYxLldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlMAESiAEKH0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb24SMS5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QaMi5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlc3BvbnNlEnQKF1JlY2hlY2tNY3BBdXRob3JpemF0aW9uEikubWVjYXRsLnYxLlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBoqLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlKAEwARJxChZDYW5jZWxNY3BBdXRob3JpemF0aW9uEigubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0GikubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAESTwoMTGlzdFNlc3Npb25zEh4ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdFNlc3Npb25zUmVzcG9uc2USWwoQR2V0U3RvcmFnZUhlYWx0aBIiLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVxdWVzdBojLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVzcG9uc2USYQoSUGxhblNlc3Npb25DbGVhbnVwEiQubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlcXVlc3QaJS5tZWNhdGwudjEuUGxhblNlc3Npb25DbGVhbnVwUmVzcG9uc2USUwoTQXBwbHlTZXNzaW9uQ2xlYW51cBIlLm1lY2F0bC52MS5BcHBseVNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFENhbmNlbFNlc3Npb25DbGVhbnVwEiYubWVjYXRsLnYxLkNhbmNlbFNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFEdldFNlc3Npb25DbGVhbnVwSm9iEiYubWVjYXRsLnYxLkdldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iEkkKCkxpc3RTa2lsbHMSHC5tZWNhdGwudjEuTGlzdFNraWxsc1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdFNraWxsc1Jlc3BvbnNlElUKDkxpc3RTa2lsbEZpbGVzEiAubWVjYXRsLnYxLkxpc3RTa2lsbEZpbGVzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0U2tpbGxGaWxlc1Jlc3BvbnNlElIKDVJlYWRTa2lsbEZpbGUSHy5tZWNhdGwudjEuUmVhZFNraWxsRmlsZVJlcXVlc3QaIC5tZWNhdGwudjEuUmVhZFNraWxsRmlsZVJlc3BvbnNlEkAKB0dldFNvdWwSGS5tZWNhdGwudjEuR2V0U291bFJlcXVlc3QaGi5tZWNhdGwudjEuR2V0U291bFJlc3BvbnNlEk8KDEdldFVzZXJNb2RlbBIeLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldFVzZXJNb2RlbFJlc3BvbnNlElUKDlJlZmxlY3RTZXNzaW9uEiAubWVjYXRsLnYxLlJlZmxlY3RTZXNzaW9uUmVxdWVzdBohLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlc3BvbnNlEmEKEkdldExlYXJuaW5nQXR0ZW1wdBIkLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GiUubWVjYXRsLnYxLkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmcKFExpc3RMZWFybmluZ0F0dGVtcHRzEiYubWVjYXRsLnYxLkxpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBonLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1Jlc3BvbnNlEmkKFFJldHJ5TGVhcm5pbmdBdHRlbXB0EicubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QaKC5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USawoWQWJhbmRvbkxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEl4KEUdlbmVyYXRlRHJlYW1QbGFuEiMubWVjYXRsLnYxLkdlbmVyYXRlRHJlYW1QbGFuUmVxdWVzdBokLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlElgKD0RlY2lkZURyZWFtUGxhbhIhLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXF1ZXN0GiIubWVjYXRsLnYxLkRlY2lkZURyZWFtUGxhblJlc3BvbnNlEmoKFUxpc3RMZWFybmluZ1Byb3Bvc2FscxInLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXF1ZXN0GigubWVjYXRsLnYxLkxpc3RMZWFybmluZ1Byb3Bvc2Fsc1Jlc3BvbnNlEmQKE0dldExlYXJuaW5nUHJvcG9zYWwSJS5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaJi5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEm0KFkRlY2lkZUxlYXJuaW5nUHJvcG9zYWwSKC5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaKS5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEmoKFVVuZG9MZWFybmluZ1Byb21vdGlvbhInLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXF1ZXN0GigubWVjYXRsLnYxLlVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEl4KEUxpc3RMZWFybmVkU2tpbGxzEiMubWVjYXRsLnYxLkxpc3RMZWFybmVkU2tpbGxzUmVxdWVzdBokLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlElgKD0dldExlYXJuZWRTa2lsbBIhLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXF1ZXN0GiIubWVjYXRsLnYxLkdldExlYXJuZWRTa2lsbFJlc3BvbnNlEnMKGERpZmZMZWFybmVkU2tpbGxWZXJzaW9ucxIqLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXF1ZXN0GisubWVjYXRsLnYxLkRpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1Jlc3BvbnNlEmMKFEFjdGl2YXRlTGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYQoSUmVqZWN0TGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYgoTQXJjaGl2ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmUKFFJvbGxiYWNrTGVhcm5lZFNraWxsEiYubWVjYXRsLnYxLlJvbGxiYWNrTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJbChBMaXN0U2tpbGxDaGFuZ2VzEiIubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXF1ZXN0GiMubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXNwb25zZRJJCgpMaXN0TW9kZWxzEhwubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXNwb25zZRJJCgpDcmVhdGVUZWFtEhwubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXF1ZXN0Gh0ubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXNwb25zZRJSCg1TcGF3blRlYW1tYXRlEh8ubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXF1ZXN0GiAubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXNwb25zZRJkChNTZW5kVGVhbW1hdGVNZXNzYWdlEiUubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXF1ZXN0GiYubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXNwb25zZRJVCg5DYW5jZWxUZWFtbWF0ZRIgLm1lY2F0bC52MS5DYW5jZWxUZWFtbWF0ZVJlcXVlc3QaIS5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXNwb25zZRI8CgdSdW5UZWFtEhkubWVjYXRsLnYxLlJ1blRlYW1SZXF1ZXN0GhQubWVjYXRsLnYxLlRlYW1FdmVudDABEkMKCExpc3RUZWFtEhoubWVjYXRsLnYxLkxpc3RUZWFtUmVxdWVzdBobLm1lY2F0bC52MS5MaXN0VGVhbVJlc3BvbnNlEkwKC0NsZWFudXBUZWFtEh0ubWVjYXRsLnYxLkNsZWFudXBUZWFtUmVxdWVzdBoeLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlc3BvbnNlEkAKC0FwcHJvdmVQbGFuEh0ubWVjYXRsLnYxLkFwcHJvdmVQbGFuUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmgKGENvbm5lY3RXb3Jrc3BhY2VTZXJ2aWNlcxIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29ubmVjdFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudBJoChhSZXRyeVdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaQoZQ2FuY2VsV29ya3NwYWNlRW5yb2xsbWVudBIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudEKiAQoNY29tLm1lY2F0bC52MUIMSGFybmVzc1Byb3RvUAFaPmdpdGh1Yi5jb20vc3RhY2tsb2svbWVjYXRsL2NvbnRyYWN0cy9nZW4vZ28vbWVjYXRsL3YxO21lY2F0bHYxogIDTVhYqgIJTWVjYXRsLlYxygIJTWVjYXRsXFYx4gIVTWVjYXRsXFYxXEdQQk1ldGFkYXRh6gIKTWVjYXRsOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_google_protobuf_timestamp]); /** * Limits are the configured stop conditions for a session. A zero value in @@ -685,12 +685,10 @@ export type ServerCapabilities = Message<"mecatl.v1.ServerCapabilities"> & { /** * posture is the SERVER-WIDE operator posture-ladder tier ("strict"/"trusted"/ - * "auto"/"yolo"). It is CHROME ONLY — a client renders an honest "⚠ auto"/"⚠ yolo" - * badge so an operator can see the daemon's automation posture at a glance — and is + * "auto"/"yolo"). It bounds which session modes a client may cycle to and is * NEVER session state (it does not change per session; permission MODE is the * per-session knob). String passthrough, no enum on the wire (the EvNoProgress / - * StopBudget discipline). Additive: an older server leaves it empty and the client - * shows no badge (strict/trusted also show no badge). + * StopBudget discipline). Additive: an older server leaves it empty. * * @generated from field: string posture = 13; */ @@ -834,6 +832,16 @@ export type ServerCapabilities = Message<"mecatl.v1.ServerCapabilities"> & { * @generated from field: bool execution_templates = 31; */ executionTemplates: boolean; + + /** + * project_trusted reports whether the server trusts its launch workspace's + * project content (rules, instructions, soul). It is an axis separate from + * the permission mode. CHROME ONLY. Additive: an older server leaves it + * unset and the client shows no trust indicator. + * + * @generated from field: optional bool project_trusted = 32; + */ + projectTrusted?: boolean | undefined; }; /** diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index ee0c011fbb..0992ed7d78 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -138,8 +138,11 @@ The restart a posture change needs depends on how you connect: - Under `mecatui connect`, the server operator changes `mecated`'s configuration and restarts it. Relaunching the client changes nothing. -The `mecatui` header shows the session mode and, whenever the posture is above -`strict`, the posture as well (`trusted`, `auto`, or `yolo`). +The `mecatui` header shows the session mode, which changes as you cycle; `yolo` +appears as a red `YOLO` pill. The top-right corner shows whether the server +trusts the project: `trusted` or +`untrusted`. Project trust is independent of the mode. An older server that +does not report trust shows no trust label. Press `?` in `mecatui` to see every mode, the two things each one sets, and the restart that applies to your connection. @@ -183,10 +186,12 @@ choice for you: they pass the checker model you configure, or `--guardrails off` when you leave it empty. See [Guardrails for mecak8s](/operating/mecak8s.md#choose-a-guardrails-checker) and the [`mecatequi` action inputs](/building/ci/mecatequi.md#headless-posture-and-permission-asks). -At `yolo`, a configured checker is advisory only. It has no pre-tool veto, no -approve-once human ask, and no fail-closed behavior when the checker fails, so a -checker outage looks the same as a clean result. The startup line reports it as -`advisory`. Choose `auto` when you want the checker to block findings. +In a session running in `yolo` mode, a configured checker is advisory only. It +has no pre-tool veto, no approve-once human ask, and no fail-closed behavior when +the checker fails, so a checker outage looks the same as a clean result. The +startup line reports it as `advisory`. Choose `auto` when you want the checker to +block findings. On a server started with `yolo`, a session you switch to `auto` +or a lower mode keeps the checker enforcing. ## Headless roots and project trust diff --git a/user-docs/mecatui/status-line.md b/user-docs/mecatui/status-line.md index 732215b619..9154d0cb03 100644 --- a/user-docs/mecatui/status-line.md +++ b/user-docs/mecatui/status-line.md @@ -126,7 +126,7 @@ refreshes it. |JSON path|Type|Meaning| |-|-|-| -|`Version`|integer|Status input protocol version (currently `5`).| +|`Version`|integer|Status input protocol version (currently `6`).| |`Server.DisplayTarget`|string|Credential-free target shown by the client.| |`Server.ConnectionMode`|string|`embedded`, `connect`, or empty while unknown.| |`Session.Title`|string|Optional display title.| @@ -149,6 +149,7 @@ refreshes it. |`Workspace.Path`|string|Exact local root returned by the privileged local-context RPC. It is available to templates through their escaped projection and to a configured direct local status command. It is empty for remote, untrusted, no-FS, unavailable, and otherwise ineligible sessions.| |`Terminal.Rows`, `Terminal.Cols`|integers|Measured terminal dimensions.| |`Terminal.HeaderAvailCols`, `Terminal.FooterAvailCols`|integers|Columns remaining after the client reserves mandatory header and footer lanes.| +|`Terminal.Emoji`|boolean|Whether the terminal is likely to draw emoji such as ⚡️ at their expected width. The shipped header uses it to add a bolt before the `yolo` pill.| |`MainAgent.State`|string|`connecting`, `idle`, `thinking`, `running_tool`, `awaiting_approval`, `completed`, `failed`, or `cancelled`.| |`MainAgent.Activity`|string|Bounded display activity label.| |`MainAgent.Approval`|string|`none` or `awaiting`.| @@ -179,7 +180,12 @@ left-aligned by the renderer; footers are right-aligned. Text may be wrapped in these semantic tokens: `text`, `muted`, `primary`, `secondary`, `accent`, `success`, `warning`, -`error`, and `info`. +`error`, `info`, and `danger`. + +`danger` fills its text with a fixed red background that doesn't change with the +theme. It is the pill the default header uses for `yolo` mode. The fill covers +exactly the wrapped text, so include any padding spaces inside the element, for +example ` YOLO `. A link keeps its display text separate from its destination. Use the StatusML `` element instead of the HTML `` element. It must be a direct child of diff --git a/user-docs/reference/grpc-schema.md b/user-docs/reference/grpc-schema.md index e37d5ffca9..66fea81a3f 100644 --- a/user-docs/reference/grpc-schema.md +++ b/user-docs/reference/grpc-schema.md @@ -3046,7 +3046,7 @@ old clients ignore and new clients reading an old server see as false. | `soul` | `bool` | | | soul is true when a soul source is wired (a soul was selected at startup, so GetSoul returns its snapshot). Gates the /soul read-only inspection panel. | | `user_model` | `bool` | | | user_model is true when the user-model store is wired (GetUserModel reads its live index). Gates the /memory read-only inspection panel. | | `model_selection` | `bool` | | | model_selection is true when >=1 provider is available (ListModels would return >0). Gates the client's /models picker the same way `agents` gates /agents. Additive: an older server leaves it false and the client hides the picker. (multi-provider Phase 0, S3.) | -| `posture` | `string` | | | posture is the SERVER-WIDE operator posture-ladder tier ("strict"/"trusted"/ "auto"/"yolo"). It is CHROME ONLY — a client renders an honest "⚠ auto"/"⚠ yolo" badge so an operator can see the daemon's automation posture at a glance — and is NEVER session state (it does not change per session; permission MODE is the per-session knob). String passthrough, no enum on the wire (the EvNoProgress / StopBudget discipline). Additive: an older server leaves it empty and the client shows no badge (strict/trusted also show no badge). | +| `posture` | `string` | | | posture is the SERVER-WIDE operator posture-ladder tier ("strict"/"trusted"/ "auto"/"yolo"). It bounds which session modes a client may cycle to and is NEVER session state (it does not change per session; permission MODE is the per-session knob). String passthrough, no enum on the wire (the EvNoProgress / StopBudget discipline). Additive: an older server leaves it empty. | | `worktrees` | `bool` | | | worktrees is true when a WorktreeLister is wired (ListWorktrees may return a non-empty list for a real git repo). Gates the client's /worktrees overlay — the first-class operator workflow for binding a session to an EXISTING sibling git worktree (issue #102). Additive: an older server leaves it false and the client hides the overlay. A no-FS/cloud server (no lister wired) also yields false, so the feature is honestly absent there. | | `scheduling` | `bool` | | | scheduling is true when a ScheduleStore is reachable (the schedule RPCs are functional: Create/List/Get/Pause/Resume/Delete/FireNow/GetFire/ListFires). Gates the client's /schedule overlay. Independent of the scheduler tick loop (--scheduler): the store-backed RPCs work without the tick loop. Additive: an older server leaves it false and the client hides the overlay. | | `reflection` | `bool` | | | reflection is true when explicit completed-session reflection is available. | @@ -3063,6 +3063,7 @@ old clients ignore and new clients reading an old server see as false. | `mcp_connector_status` | `bool` | | | mcp_connector_status requires a wired broker inspector, enforced ownership and a verified caller. It does not enable direct MCP resources or prompts. | | `mcp_refresh` | `bool` | | | mcp_refresh is true when direct/global MCP source reconciliation is wired. It is mutually exclusive with workspace_enrollment in a valid deployment. | | `execution_templates` | `bool` | | | execution_templates is true only when an authenticated template catalog is wired; an eligible inventory may still be empty. | +| `project_trusted` | `bool` | optional | | project_trusted reports whether the server trusts its launch workspace's project content (rules, instructions, soul). It is an axis separate from the permission mode. CHROME ONLY. Additive: an older server leaves it unset and the client shows no trust indicator. | diff --git a/user-docs/reference/server-cli.md b/user-docs/reference/server-cli.md index 4cfde8722d..d5c74c028b 100644 --- a/user-docs/reference/server-cli.md +++ b/user-docs/reference/server-cli.md @@ -365,13 +365,12 @@ Flags: path to a repeatable YAML permission configuration. CLI rules have highest precedence; configured deny and ask rules always override allows. --permission-mode string - permission mode, one of: plan, default, accept-edits, trusted, trusted-accept- - edits, auto, yolo. Sets two things: the process-wide posture, fixed at startup - (strict for plan, default, and accept-edits; trusted for trusted and trusted- - accept-edits; auto; yolo), and the session mode new sessions start in, which - each session may change. Default: default. auto and yolo allow tools without - asking, so they need a guardrails checker (--guardrails-model) or an explicit - - -guardrails off, and are refused for root unless MECATL_SANDBOX=1 or + permission mode, one of: plan, default, accept-edits, auto, yolo. Sets two + things: the process-wide posture, fixed at startup (strict for plan, default, + and accept-edits; auto; yolo), and the session mode new sessions start in, + which each session may change. Default: default. auto and yolo allow tools + without asking, so they need a guardrails checker (--guardrails-model) or an + explicit --guardrails off, and are refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1. Deny rules and configured ask rules still apply. Replaces the deprecated --posture and --yolo; --trust-project still combines with it. --permissions-conventional @@ -819,11 +818,10 @@ Usage: mecak8s [flags] --permission-config value Trusted permission YAML file. Repeatable --permission-mode string - Permission mode, one of: plan, default, accept-edits, trusted, trusted-accept- - edits, auto, yolo. Sets two things: the process-wide posture, fixed at startup - (strict for plan, default, and accept-edits; trusted for trusted and trusted- - accept-edits; auto; yolo), and the session mode new sessions start in, which - each session may change. Default: auto (posture auto, default session mode). + Permission mode, one of: plan, default, accept-edits, auto, yolo. Sets two + things: the process-wide posture, fixed at startup (strict for plan, default, + and accept-edits; auto; yolo), and the session mode new sessions start in, + which each session may change. Default: auto (posture auto, auto session mode). auto and yolo allow tools without asking, so they need a guardrails checker (-- guardrails-model or the guardrail model slot) or an explicit --guardrails off, and require MECATL_SANDBOX when running as root. Deny rules and configured ask From 316ab0da6b0377e05f737104659a386537d059eb Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Thu, 15 Oct 2026 16:59:01 +0300 Subject: [PATCH 23/48] fix(sdk): project ServerCapabilities.projectTrusted in the TypeScript SDK The server now sends the optional project_trusted capability, but the SDK's capability projection did not copy it and the descriptor guard test failed (expected 29 fields, got 30). Project it as an optional field so older servers that leave it unset stay distinguishable, and refresh the API reports and SDK reference. Co-authored-by: Mecatl --- sdk/typescript/etc/mecatl-sdk-deno.api.md | 1 + sdk/typescript/etc/mecatl-sdk-node.api.md | 1 + sdk/typescript/etc/mecatl-sdk.api.md | 1 + sdk/typescript/src/session-projections.ts | 3 +++ sdk/typescript/test/session-projections.test.ts | 1 + user-docs/reference/typescript-sdk-api/core.md | 8 ++++++++ 6 files changed, 15 insertions(+) diff --git a/sdk/typescript/etc/mecatl-sdk-deno.api.md b/sdk/typescript/etc/mecatl-sdk-deno.api.md index 3e120ba8ee..fecb875880 100644 --- a/sdk/typescript/etc/mecatl-sdk-deno.api.md +++ b/sdk/typescript/etc/mecatl-sdk-deno.api.md @@ -1317,6 +1317,7 @@ export interface ServerCapabilities { readonly modelSelection: boolean; // (undocumented) readonly posture: string; + readonly projectTrusted?: boolean; // (undocumented) readonly reflection: boolean; // (undocumented) diff --git a/sdk/typescript/etc/mecatl-sdk-node.api.md b/sdk/typescript/etc/mecatl-sdk-node.api.md index 200242841c..fbd38d6c81 100644 --- a/sdk/typescript/etc/mecatl-sdk-node.api.md +++ b/sdk/typescript/etc/mecatl-sdk-node.api.md @@ -1346,6 +1346,7 @@ export interface ServerCapabilities { readonly modelSelection: boolean; // (undocumented) readonly posture: string; + readonly projectTrusted?: boolean; // (undocumented) readonly reflection: boolean; // (undocumented) diff --git a/sdk/typescript/etc/mecatl-sdk.api.md b/sdk/typescript/etc/mecatl-sdk.api.md index 9697fc37c7..940a9bb01b 100644 --- a/sdk/typescript/etc/mecatl-sdk.api.md +++ b/sdk/typescript/etc/mecatl-sdk.api.md @@ -1269,6 +1269,7 @@ export interface ServerCapabilities { readonly modelSelection: boolean; // (undocumented) readonly posture: string; + readonly projectTrusted?: boolean; // (undocumented) readonly reflection: boolean; // (undocumented) diff --git a/sdk/typescript/src/session-projections.ts b/sdk/typescript/src/session-projections.ts index 5c228e4201..b334d99156 100644 --- a/sdk/typescript/src/session-projections.ts +++ b/sdk/typescript/src/session-projections.ts @@ -124,6 +124,8 @@ export interface ServerCapabilities { readonly userModel: boolean; readonly modelSelection: boolean; readonly posture: string; + /** Whether the server trusts its launch workspace; absent from older servers. */ + readonly projectTrusted?: boolean; readonly worktrees: boolean; readonly scheduling: boolean; readonly reflection: boolean; @@ -263,6 +265,7 @@ export function projectServerCapabilities(value: ProtoServerCapabilities): Serve memory: value.memory, modelSelection: value.modelSelection, posture: value.posture, + ...(value.projectTrusted === undefined ? {} : { projectTrusted: value.projectTrusted }), reflection: value.reflection, scheduling: value.scheduling, sessionDebug: value.sessionDebug, diff --git a/sdk/typescript/test/session-projections.test.ts b/sdk/typescript/test/session-projections.test.ts index f489802fbe..5ff46d3a80 100644 --- a/sdk/typescript/test/session-projections.test.ts +++ b/sdk/typescript/test/session-projections.test.ts @@ -312,6 +312,7 @@ describe("session projections", () => { "memory", "modelSelection", "posture", + "projectTrusted", "reflection", "scheduling", "sessionDebug", diff --git a/user-docs/reference/typescript-sdk-api/core.md b/user-docs/reference/typescript-sdk-api/core.md index e74df0410b..4ba1c82cda 100644 --- a/user-docs/reference/typescript-sdk-api/core.md +++ b/user-docs/reference/typescript-sdk-api/core.md @@ -4445,6 +4445,14 @@ readonly modelSelection: boolean; readonly posture: string; ``` +ServerCapabilities.projectTrusted + +Whether the server trusts its launch workspace; absent from older servers. + +```ts +readonly projectTrusted?: boolean; +``` + ServerCapabilities.reflection ```ts From fd6f4c79e32c4206777d13990f588b3e51c96054 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 11:58:30 +0300 Subject: [PATCH 24/48] fix(permissions): address review on session-scoped permission modes Enforce the selected session mode across every layer and caller: - Re-admit a stored session's mode against the current ceiling and checker at every run entry, approval resume, fork, and clear (FailedPrecondition, history untouched). - Remove auto's default-mode exemption: auto needs an enforcing checker at startup, creation, and SetMode; unchecked autonomy is yolo. - Drive the out-of-workspace escape policy and its checker route from the session mode instead of the process posture. - mecatequi runs in the mode resolved from --permission-mode. - A --permission-mode token never grants project trust. - Helm chart and mecatequi action distinguish inherit / model / off for the guardrails checker; the chart gains permissionMode. - mecatui no longer blocks the composer on an unavailable mode. - TypeScript SDK supports Auto/Yolo over gRPC and HTTP, omits an unspecified create mode, and projects new capabilities. - Advertise the session_permission_modes feature and the optional subagent_ask_reviewer capability (shown in /posture). - Delegated children inherit an auto or yolo parent's mode. - ACP starts sessions in the server default mode and offers only admitted modes. - Share one deprecated-posture replacement mapping across the roots. - Document the five-mode contract, the upgrade from the posture model, and the narrower pending-approval contract. Co-authored-by: Mecatl --- .github/actions/mecatequi/action.yml | 37 +- .github/workflows/mecatequi-reusable.yml | 12 +- .github/workflows/mecatequi.yml | 7 +- cmd/mecak8s/main_test.go | 6 +- cmd/mecak8s/mcp_test.go | 2 +- cmd/mecak8s/permission_mode.go | 25 +- cmd/mecak8s/permission_mode_test.go | 108 +- cmd/mecak8s/telemetry_test.go | 6 +- cmd/mecated/permission_mode.go | 24 +- cmd/mecatequi/main.go | 6 +- cmd/mecatequi/permission_mode.go | 25 +- cmd/mecatequi/permission_mode_test.go | 151 +- cmd/mecatequi/run.go | 5 +- cmd/mecatequi/run_test.go | 45 + cmd/mecatui/client/capabilities.go | 4 + cmd/mecatui/client/capabilities_test.go | 5 + cmd/mecatui/config.go | 2 +- cmd/mecatui/customization/defaults.go | 2 +- cmd/mecatui/permission_mode.go | 16 +- cmd/mecatui/ui/builtins.go | 29 +- cmd/mecatui/ui/help.go | 10 +- cmd/mecatui/ui/keys.go | 4 +- cmd/mecatui/ui/mode_cycle.go | 130 +- cmd/mecatui/ui/mode_test.go | 13 +- .../ui/permission_mode_vocabulary_test.go | 163 +- cmd/mecatui/ui/posture_badge_test.go | 37 +- cmd/mecatui/ui/testdata/help_all_on.golden | 2 +- cmd/mecatui/ui/testdata/help_embedded.golden | 2 +- cmd/mecatui/ui/update.go | 18 +- cmd/mecatui/ui/view.go | 13 - contracts/gen/go/mecatl/v1/harness.pb.go | 6255 +++++++++-------- contracts/proto/mecatl/v1/harness.proto | 7 + deploy/helm/mecak8s/chart_test.go | 74 +- deploy/helm/mecak8s/templates/_helpers.tpl | 17 + deploy/helm/mecak8s/templates/deployment.yaml | 5 +- deploy/helm/mecak8s/values.schema.json | 4 +- deploy/helm/mecak8s/values.yaml | 35 +- docs/architecture/governance.md | 65 +- engine/CHANGELOG.md | 8 + engine/agent/child_mode_inherit_test.go | 86 + engine/agent/dispatch.go | 1 + engine/agent/export_test.go | 3 + engine/agent/parallel.go | 7 +- engine/agent/subagent.go | 34 +- engine/agent/teamtool.go | 5 + internal/adapter/acp/agent.go | 46 +- internal/adapter/acp/mode_admission_test.go | 63 + internal/adapter/permconfig/schema.go | 7 +- internal/adapter/server/classification.go | 1 + .../adapter/server/compatibility_info_test.go | 59 + internal/adapter/server/features.go | 9 + .../adapter/server/mode_admission_test.go | 125 +- .../adapter/server/placement_successor.go | 5 + .../adapter/server/resume_awaiting_test.go | 53 + .../server/sdk_typescript_release_test.go | 1 + internal/adapter/server/service.go | 91 +- internal/app/build.go | 41 +- .../app/contextual_guardrail_usage_test.go | 14 +- internal/app/escapeclassifier_test.go | 10 +- internal/app/escapepolicy.go | 92 +- internal/app/guardrails.go | 2 +- internal/app/listdir_external_posture_test.go | 8 +- internal/app/microvm_harness_context_test.go | 4 +- internal/app/pathescape_guardrail_test.go | 74 +- internal/app/pathescape_scenario2_test.go | 21 +- internal/app/pathescape_scenario3_test.go | 192 +- internal/app/pathescape_scenario4_test.go | 52 +- internal/app/pathescape_scenario5_test.go | 2 +- internal/app/pathescape_scenario5b_test.go | 4 +- internal/app/permission_mode.go | 96 +- internal/app/permission_mode_test.go | 154 +- internal/app/posture.go | 8 + internal/app/posture_build_test.go | 104 +- internal/app/project_ingestion_build_test.go | 10 +- internal/app/relative_authority_test.go | 2 +- internal/app/relative_escape_test.go | 8 +- internal/app/remote_execution_test.go | 2 +- internal/app/self_knowledge_posture_test.go | 15 + internal/app/test_helpers_test.go | 18 + internal/configgen/build.go | 11 +- internal/configgen/settings.skeleton.yaml | 16 +- sdk/typescript/etc/mecatl-sdk-deno.api.md | 4 + sdk/typescript/etc/mecatl-sdk-node.api.md | 4 + sdk/typescript/etc/mecatl-sdk.api.md | 4 + .../src/gen/mecatl/v1/harness_pb.ts | 14 +- sdk/typescript/src/http.ts | 15 +- sdk/typescript/src/server.ts | 1 + sdk/typescript/src/session-projections.ts | 16 +- sdk/typescript/test/package.test.ts | 2 +- sdk/typescript/test/server-discovery.test.ts | 68 + .../test/session-lifecycle-transports.test.ts | 142 + .../test/session-projections.test.ts | 1 + user-docs/building/ci/mecatequi.md | 27 +- .../permissions-and-posture.md | 185 +- user-docs/mecatui/keybindings.md | 2 +- user-docs/mecatui/using-the-tui.md | 11 +- user-docs/operating/mecak8s.md | 41 +- .../operating/mecated/secure-and-expose.md | 19 +- user-docs/reference/configuration.md | 4 +- user-docs/reference/grpc-schema.md | 1 + user-docs/reference/server-cli.md | 33 +- .../reference/typescript-sdk-api/core.md | 11 + 102 files changed, 5487 insertions(+), 4053 deletions(-) create mode 100644 engine/agent/child_mode_inherit_test.go create mode 100644 internal/adapter/acp/mode_admission_test.go diff --git a/.github/actions/mecatequi/action.yml b/.github/actions/mecatequi/action.yml index 5c1ebb67bf..f38ddaae20 100644 --- a/.github/actions/mecatequi/action.yml +++ b/.github/actions/mecatequi/action.yml @@ -126,12 +126,14 @@ inputs: default: ${{ github.workspace }} permission-mode: description: >- - Permission mode → --permission-mode: one of plan, default, accept-edits, - trusted, trusted-accept-edits, auto, yolo. Empty (the input default) resolves to - "auto", the documented CI mode (allow-all, child injection-defence ON), unless the - deprecated `posture` input is set. "default" would CANCEL the run on the first - mutate because a headless run has no approver. auto and yolo need a checker choice; - see `guardrails-model`. Setting both this and `posture` fails the step. + Permission mode → --permission-mode: one of plan, default, accept-edits, auto, + yolo. Empty (the input default) resolves to "auto", the documented CI mode + (allow-all, child injection-defence ON), unless the deprecated `posture` input is + set. auto refuses to start without an ENFORCING guardrails checker, inherited from + operator settings or named with `guardrails-model`. yolo is the explicit choice to + run allow-all with no checker. "default" would CANCEL the run on the first mutate + because a headless run has no approver. Setting both this and `posture` fails the + step. required: false default: "" posture: @@ -196,12 +198,13 @@ inputs: guardrails-model: description: >- GUARDRAILS (issue #27) checker model id / alias inspecting outbound args + inbound - results → --guardrails-model. mecatequi refuses an allow-all permission mode (auto, - yolo) with no checker unless the opt-out is explicit, so this action always declares - the choice: a non-empty value passes --guardrails-model; empty (default) passes - --guardrails off, a DELIBERATE choice to run unsupervised with nothing inspecting - tool content. The kill-switch also disables a guardrail model slot from settings, - so name the checker here if you want one. + results. Empty (default) passes no guardrails flag, so the binary uses the checker + configured in operator settings (a `guardrails:` model or the `guardrail` model + slot), if any. The literal "off" passes --guardrails off, the kill-switch, which + also disables a checker configured in settings. Any other value passes + --guardrails-model . The auto permission mode refuses to start without an + enforcing checker, so pair "off" or an unconfigured empty value with + `permission-mode: yolo`. required: false default: "" subagent-ask-reviewer: @@ -458,12 +461,12 @@ runs: [ -n "${MQ_DEFAULT_MODEL}" ] && args+=( --default-model "${MQ_DEFAULT_MODEL}" ) [ "${openai_on}" = "true" ] && args+=( --openai ) [ -n "${MQ_OPENAI_BASE_URL}" ] && args+=( --openai-base-url "${MQ_OPENAI_BASE_URL}" ) - # Checker choice is ALWAYS declared: a named checker, or the explicit unsupervised - # kill-switch (an allow-all mode with neither is refused at startup). - if [ -n "${MQ_GUARDRAILS_MODEL}" ]; then - args+=( --guardrails-model "${MQ_GUARDRAILS_MODEL}" ) - else + # Checker choice: empty inherits the operator-settings checker (no flag), "off" + # is the explicit kill-switch, anything else names the checker model. + if [ "${MQ_GUARDRAILS_MODEL}" = "off" ]; then args+=( --guardrails off ) + elif [ -n "${MQ_GUARDRAILS_MODEL}" ]; then + args+=( --guardrails-model "${MQ_GUARDRAILS_MODEL}" ) fi [ -n "${MQ_ASK_REVIEWER}" ] && args+=( --subagent-ask-reviewer "${MQ_ASK_REVIEWER}" ) [ -n "${MQ_ASK_REVIEWER_MAX_DENIES}" ] && args+=( --subagent-ask-reviewer-max-denies "${MQ_ASK_REVIEWER_MAX_DENIES}" ) diff --git a/.github/workflows/mecatequi-reusable.yml b/.github/workflows/mecatequi-reusable.yml index 40b9ff7285..f9ad728132 100644 --- a/.github/workflows/mecatequi-reusable.yml +++ b/.github/workflows/mecatequi-reusable.yml @@ -47,8 +47,11 @@ on: default: "" posture: description: >- - Operator posture ladder (strict < trusted < auto < yolo). Default "auto" — the - documented CI posture (allow-all, child injection-defence ON). + Passed to the action's DEPRECATED `posture` input (the binary WARNs): strict, + trusted, auto, or yolo. Default "auto" resolves to permission mode auto (allow-all, + child injection-defence ON), which refuses to start without an ENFORCING + guardrails checker; use "yolo" to run allow-all with no checker. It never grants + project trust. type: string required: false default: auto @@ -84,7 +87,10 @@ on: guardrails-model: description: >- Guardrails (issue #27) checker model id / alias that inspects outbound tool args + - inbound results. Empty (default) disables guardrails. + inbound results. Empty (default) passes no guardrails flag, so the checker + configured in operator settings applies, if any. "off" is the kill-switch. Any + other value names the checker model. With posture "auto", an empty value and no + settings checker, or "off", refuses to start. type: string required: false default: "" diff --git a/.github/workflows/mecatequi.yml b/.github/workflows/mecatequi.yml index dc6d549356..251616a237 100644 --- a/.github/workflows/mecatequi.yml +++ b/.github/workflows/mecatequi.yml @@ -221,9 +221,10 @@ jobs: with: prompt-file: ${{ steps.prompt.outputs.prompt-file }} untrusted: "true" - permission-mode: "auto" - # No guardrails-model: the action passes --guardrails off, a deliberate - # unsupervised choice for this private, split-privilege CI run. + # yolo: a deliberate unchecked choice for this private, split-privilege CI + # run. auto would refuse to start because no guardrails checker is configured. + permission-mode: "yolo" + guardrails-model: "off" # Use `model` (per-session passthrough), NOT `default-model`: a deployment # default is validated against the embedded models.dev catalog at startup, and # claude-sonnet-4.6 is newer than that snapshot (it would fail "not catalogued"). diff --git a/cmd/mecak8s/main_test.go b/cmd/mecak8s/main_test.go index f467fc8577..ce47bca437 100644 --- a/cmd/mecak8s/main_test.go +++ b/cmd/mecak8s/main_test.go @@ -452,8 +452,8 @@ func TestBuildOverRedisDrivesRunToCompletion(t *testing.T) { RedisURL: mr.Addr(), RedisAllowPlaintext: true, Interactive: false, // mecak8s headless default (Interactive=!headless) - Posture: app.PostureAuto, - GuardrailsDisabled: true, // allow-all declares its checker choice + Posture: app.PostureYolo, + GuardrailsDisabled: true, // unchecked allow-all is yolo PermissionsConventional: false, AgentsConventional: false, Diagnostics: port.NopDiagnostics{}, @@ -627,7 +627,7 @@ func TestDrainHTTPRouting(t *testing.T) { func TestServeWiresSeparateDrainListener(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", - "--guardrails=off", // the auto default must declare its checker choice + "--permission-mode=yolo", "--guardrails=off", // unchecked allow-all is yolo "--grpc-addr", freeLoopbackPort(t), "--http-addr", freeLoopbackPort(t), "--drain-addr", freeLoopbackPort(t), diff --git a/cmd/mecak8s/mcp_test.go b/cmd/mecak8s/mcp_test.go index 21622db97e..5a83aef7e1 100644 --- a/cmd/mecak8s/mcp_test.go +++ b/cmd/mecak8s/mcp_test.go @@ -60,7 +60,7 @@ func TestMecak8sBuildDiscoversOperatorMCPSettings(t *testing.T) { if err := os.WriteFile(explicit, []byte("mcp:\n mode: global\n servers:\n - name: explicit\n url: https://mcp.example/mcp\n auth: {mode: none}\n"), 0o600); err != nil { t.Fatal(err) } - cfg, err = parseFlags([]string{"--permission-config", explicit, "--guardrails=off"}) + cfg, err = parseFlags([]string{"--permission-config", explicit, "--permission-mode=yolo", "--guardrails=off"}) if err != nil { t.Fatal(err) } diff --git a/cmd/mecak8s/permission_mode.go b/cmd/mecak8s/permission_mode.go index 3f05766d23..8a3977ce7a 100644 --- a/cmd/mecak8s/permission_mode.go +++ b/cmd/mecak8s/permission_mode.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/stacklok/mecatl/engine/port" - "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/internal/app" ) @@ -14,10 +13,9 @@ import ( // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + - ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; auto; yolo), " + - "and the session mode new sessions start in, which each session may change. Default: auto (posture auto, auto session mode). " + - "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model or the guardrail model slot) or an explicit --guardrails off, and require MECATL_SANDBOX when running as root. " + - "Deny rules and configured ask rules still apply. Replaces the deprecated --posture; --trust-project still combines with it" + ". Sets two things: the mode new sessions start in, and the process-wide server ceiling, fixed at startup, which is the most permissive mode a session may switch to (accept-edits for plan, default, and accept-edits). Default: auto. " + + "auto and yolo allow tools without asking and require MECATL_SANDBOX when running as root. auto needs an enforcing guardrails checker (--guardrails-model or the guardrail model slot) and refuses to start without one, including with --guardrails off; yolo runs without one. " + + "Deny rules and configured ask rules still apply. A mode never grants project trust; use --trust-project. Replaces the deprecated --posture" // validatePermissionModeFlags fails fast on an unknown --permission-mode token // and on a --permission-mode combined with the deprecated --posture alias. @@ -43,20 +41,5 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { } diag.Log(context.Background(), port.LevelWarn, "--posture is DEPRECATED; use --permission-mode instead", - "posture", cfg.posture, "replacement", "--permission-mode "+postureReplacementToken(cfg.posture)) -} - -// postureReplacementToken names the token that replaces a legacy --posture value. -// auto and yolo are their own tokens; the strict-posture tiers map to "default". -func postureReplacementToken(raw string) string { - switch app.ParsePosture(raw) { - case app.PostureAuto: - return "auto" - case app.PostureYolo: - return "yolo" - } - if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { - return tok.Name - } - return "default" + "posture", cfg.posture, "replacement", "--permission-mode "+app.PostureReplacementToken(app.ParsePosture(cfg.posture))) } diff --git a/cmd/mecak8s/permission_mode_test.go b/cmd/mecak8s/permission_mode_test.go index 66704e069a..9a28c359a8 100644 --- a/cmd/mecak8s/permission_mode_test.go +++ b/cmd/mecak8s/permission_mode_test.go @@ -4,6 +4,8 @@ import ( "bytes" "context" "log/slog" + "os" + "path/filepath" "strings" "testing" @@ -124,44 +126,80 @@ func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { } func TestBareMecak8sRefusesWithoutCheckerChoice(t *testing.T) { - // The checker gate is now a startup WARN, not a refusal. - // Build succeeds; entering auto mode without a checker is refused at SetMode time. - var buf bytes.Buffer - diag := slogdiag.NewFromLogger(slog.New(slog.NewTextHandler(&buf, nil))) - cfg, err := parseFlags(nil) - if err != nil { - t.Fatalf("parseFlags: %v", err) - } - ac := appConfig(cfg, diag, observability{}) - ac.RedisURL = "" - ac.SchedulerEnabled = false - ac.SessionLeaseK8sNamespace = "" - ac.Workspace = t.TempDir() - ac.MockProvider = mockllm.New() - built, err := buildIsolated(t, context.Background(), ac) - if err != nil { - t.Fatalf("bare mecak8s must start (checker gate is now a WARN): %v", err) + // The bare default is auto, which requires an enforcing checker: no checker + // and the explicit kill-switch both refuse; unchecked autonomy is yolo. + build := func(t *testing.T, args ...string) error { + t.Helper() + cfg, err := parseFlags(args) + if err != nil { + t.Fatalf("parseFlags %v: %v", args, err) + } + ac := appConfig(cfg, port.NopDiagnostics{}, observability{}) + ac.RedisURL = "" + ac.SchedulerEnabled = false + ac.SessionLeaseK8sNamespace = "" + ac.Workspace = t.TempDir() + ac.MockProvider = mockllm.New() + built, err := buildIsolated(t, context.Background(), ac) + if err == nil { + built.Close() + } + return err } - built.Close() - if !strings.Contains(buf.String(), "no guardrails checker") || !strings.Contains(buf.String(), "--guardrails off") { - t.Errorf("bare mecak8s must WARN naming --guardrails off; log:\n%s", buf.String()) + for _, args := range [][]string{nil, {"--guardrails=off"}} { + if err := build(t, args...); err == nil || !strings.Contains(err.Error(), "requires an enforcing guardrails checker") { + t.Fatalf("mecak8s %v: err = %v, want the enforcing-checker refusal", args, err) + } } - // With --guardrails off, Build must still succeed (no checker needed). - cfgOff, err := parseFlags([]string{"--guardrails=off"}) - if err != nil { - t.Fatalf("parseFlags --guardrails=off: %v", err) - } - acOff := appConfig(cfgOff, port.NopDiagnostics{}, observability{}) - acOff.RedisURL = "" - acOff.SchedulerEnabled = false - acOff.SessionLeaseK8sNamespace = "" - acOff.Workspace = t.TempDir() - acOff.MockProvider = mockllm.New() - built2, err := buildIsolated(t, context.Background(), acOff) - if err != nil { - t.Fatalf("mecak8s with an explicit --guardrails=off: %v", err) + if err := build(t, "--permission-mode=yolo", "--guardrails=off"); err != nil { + t.Fatalf("mecak8s --permission-mode=yolo --guardrails=off must start: %v", err) + } +} + +// TestChartAutoInheritsMountedSettingsChecker covers the chart's default argv +// shape (--permission-mode=auto with no guardrails flag, because guardrails.model +// and guardrails.disabled are unset) composed with mounted operator settings: +// a checker configured there lets auto start, none refuses, and the explicit +// kill-switch (guardrails.disabled) wins over the settings checker. +func TestChartAutoInheritsMountedSettingsChecker(t *testing.T) { + settings := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(settings, []byte("guardrails:\n model: mock-checker\n"), 0o600); err != nil { + t.Fatal(err) + } + slot := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(slot, []byte("models:\n slots:\n guardrail: mock-checker\n"), 0o600); err != nil { + t.Fatal(err) + } + build := func(argv ...string) error { + t.Helper() + cfg, err := parseFlags(append([]string{"--mock", "--headless=true", "--permission-mode=auto"}, argv...)) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + ac := appConfig(cfg, port.NopDiagnostics{}, observability{}) + ac.RedisURL = "" + ac.SchedulerEnabled = false + ac.SessionLeaseK8sNamespace = "" + ac.Workspace = t.TempDir() + built, err := buildIsolated(t, context.Background(), ac) + if err == nil { + built.Close() + } + return err + } + for name, path := range map[string]string{"guardrails model": settings, "guardrail slot": slot} { + if err := build("--permission-config=" + path); err != nil { + t.Fatalf("auto with a mounted %s checker must start: %v", name, err) + } + } + for name, argv := range map[string][]string{ + "no inherited checker": nil, + "explicit kill-switch": {"--guardrails=off", "--permission-config=" + settings}, + } { + if err := build(argv...); err == nil || !strings.Contains(err.Error(), "requires an enforcing guardrails checker") { + t.Fatalf("auto with %s err = %v, want the enforcing-checker refusal", name, err) + } } - built2.Close() } func TestPermissionModeFlagConflictsAndUnknownTokens(t *testing.T) { diff --git a/cmd/mecak8s/telemetry_test.go b/cmd/mecak8s/telemetry_test.go index 0dad3f38f9..34beecdc31 100644 --- a/cmd/mecak8s/telemetry_test.go +++ b/cmd/mecak8s/telemetry_test.go @@ -227,8 +227,8 @@ func TestTelemetryMetricsAddrServesPrometheus(t *testing.T) { // A fixed free loopback port so the scrape target is deterministic. free := freeLoopbackPort(t) cfg, err := parseFlags([]string{ - "--mock", // offline: no provider key in CI - "--guardrails=off", // the auto default must declare its checker choice + "--mock", // offline: no provider key in CI + "--permission-mode=yolo", "--guardrails=off", // unchecked allow-all is yolo "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--metrics-addr", free, @@ -340,7 +340,7 @@ func TestTelemetryPushesRunMetricsOnExit(t *testing.T) { cfg, err := parseFlags([]string{ "--mock", - "--guardrails=off", // the auto default must declare its checker choice + "--permission-mode=yolo", "--guardrails=off", // unchecked allow-all is yolo "--redis-url", mr.Addr(), "--redis-allow-plaintext", // disposable miniredis fixture "--grpc-addr", "127.0.0.1:0", diff --git a/cmd/mecated/permission_mode.go b/cmd/mecated/permission_mode.go index 676391ccb2..bea9a609e3 100644 --- a/cmd/mecated/permission_mode.go +++ b/cmd/mecated/permission_mode.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/stacklok/mecatl/engine/port" - "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/internal/app" ) @@ -14,10 +13,9 @@ import ( // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + - ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; auto; yolo), " + - "and the session mode new sessions start in, which each session may change. Default: default. " + - "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model) or an explicit --guardrails off, and are refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1. " + - "Deny rules and configured ask rules still apply. Replaces the deprecated --posture and --yolo; --trust-project still combines with it." + ". Sets two things: the mode new sessions start in, and the process-wide server ceiling, fixed at startup, which is the most permissive mode a session may switch to (accept-edits for plan, default, and accept-edits). Default: default. " + + "auto and yolo allow tools without asking. auto needs an enforcing guardrails checker (--guardrails-model or the guardrail model slot) and refuses to start without one; yolo runs without one. Both are refused for root unless MECATL_SANDBOX=1 or IS_SANDBOX=1. " + + "Deny rules and configured ask rules still apply. A mode never grants project trust; use --trust-project. Replaces the deprecated --posture and --yolo." // validatePermissionModeFlags fails fast on an unknown --permission-mode token // and on a --permission-mode combined with one of its deprecated aliases, so the @@ -48,7 +46,7 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { if cfg.postureFlagSet { diag.Log(context.Background(), port.LevelWarn, "--posture is DEPRECATED; use --permission-mode instead", - "posture", cfg.posture, "replacement", "--permission-mode "+postureReplacementToken(cfg.posture)) + "posture", cfg.posture, "replacement", "--permission-mode "+app.PostureReplacementToken(app.ParsePosture(cfg.posture))) } if cfg.yoloFlagSet { diag.Log(context.Background(), port.LevelWarn, @@ -56,17 +54,3 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, cfg config) { "replacement", "--permission-mode yolo") } } - -// postureReplacementToken names the token that replaces a legacy --posture value. -// auto and yolo are their own tokens; the strict-posture tiers map to "default". -func postureReplacementToken(raw string) string { - p := app.ParsePosture(raw) - switch p { - case app.PostureAuto, app.PostureYolo: - return p.String() // "auto" or "yolo", matching the token name - } - if tok, ok := app.PermissionModeForPair(p, session.ModeDefault); ok { - return tok.Name - } - return "default" -} diff --git a/cmd/mecatequi/main.go b/cmd/mecatequi/main.go index a353ae5afd..18d234fcc7 100644 --- a/cmd/mecatequi/main.go +++ b/cmd/mecatequi/main.go @@ -24,7 +24,7 @@ // (strict), the main engine asks on every mutate — so a strict + headless run that // reaches a mutate is CANCELLED on that ask (run.Cancel, drain-to-close) and exits 1 // with an actionable "no approver" message naming the fix. The intended CI posture is -// therefore --permission-mode auto (allow-all, child injection-defense ON) or trusted/yolo, +// therefore --permission-mode auto (allow-all, child injection-defense ON) or yolo, // where the main engine does not ask. --timeout is the orthogonal wall-clock backstop. // See run()'s cancel-on-ask path and flags.posture. package main @@ -189,8 +189,8 @@ func verdictLine(sum Summary, noApprover, timedOut bool) string { return fmt.Sprintf("mecatequi: TIMED OUT — stop=%s, %s; the run exceeded --timeout and was cancelled", stop, files) case noApprover: return "mecatequi: NO APPROVER — a permission approval was requested but none is attached (--headless); " + - "re-run with --permission-mode auto|yolo (plus --guardrails-model or --guardrails off), " + - "or add allow rules (--permission-mode trusted --trust-project honours the repo's). stop=" + stop + "re-run with --permission-mode auto (with an enforcing --guardrails-model ) or yolo (no checker), " + + "or add allow rules (--trust-project honours the repo's). stop=" + stop default: return fmt.Sprintf("mecatequi: done — stop=%s, %s", stop, files) } diff --git a/cmd/mecatequi/permission_mode.go b/cmd/mecatequi/permission_mode.go index 27f96e4d26..b59e5bde2f 100644 --- a/cmd/mecatequi/permission_mode.go +++ b/cmd/mecatequi/permission_mode.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/stacklok/mecatl/engine/port" - "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/internal/app" ) @@ -14,10 +13,9 @@ import ( // both halves a token sets and their lifetimes, and lists every valid token from // the composition table so help and parsing cannot drift. var permissionModeHelp = "Permission mode, one of: " + strings.Join(app.PermissionModeNames(), ", ") + - ". Sets two things: the process-wide posture, fixed at startup (strict for plan, default, and accept-edits; auto; yolo), " + - "and the session mode the run's session starts in. Default: default. " + - "auto and yolo allow tools without asking, so they need a guardrails checker (--guardrails-model or the guardrail model slot) or an explicit --guardrails off. " + - "Deny and configured ask rules still apply. Replaces the deprecated --posture; --trust-project still combines with it." + ". Sets the mode the run's session starts in and the process-wide ceiling on the modes it may enter. Default: default. " + + "auto and yolo allow tools without asking. auto needs an enforcing guardrails checker (--guardrails-model or the guardrail model slot) and refuses to start without one; yolo runs without one. " + + "Deny and configured ask rules still apply. A mode never grants project trust; use --trust-project. Replaces the deprecated --posture." // validatePermissionModeFlags fails fast on an unknown --permission-mode token // and on a --permission-mode combined with the deprecated --posture alias. @@ -42,20 +40,5 @@ func warnDeprecatedPermissionFlags(diag port.Diagnostics, f flags) { } diag.Log(context.Background(), port.LevelWarn, "--posture is DEPRECATED; use --permission-mode instead", - "posture", f.posture, "replacement", "--permission-mode "+postureReplacementToken(f.posture)) -} - -// postureReplacementToken names the token that replaces a legacy --posture value. -// auto and yolo are their own tokens; the strict-posture tiers map to "default". -func postureReplacementToken(raw string) string { - switch app.ParsePosture(raw) { - case app.PostureAuto: - return "auto" - case app.PostureYolo: - return "yolo" - } - if tok, ok := app.PermissionModeForPair(app.ParsePosture(raw), session.ModeDefault); ok { - return tok.Name - } - return "default" + "posture", f.posture, "replacement", "--permission-mode "+app.PostureReplacementToken(app.ParsePosture(f.posture))) } diff --git a/cmd/mecatequi/permission_mode_test.go b/cmd/mecatequi/permission_mode_test.go index e31b64cb1b..a919603bda 100644 --- a/cmd/mecatequi/permission_mode_test.go +++ b/cmd/mecatequi/permission_mode_test.go @@ -2,7 +2,9 @@ package main import ( "bytes" + "context" "fmt" + "io" "log/slog" "os" "os/exec" @@ -15,6 +17,7 @@ import ( "sigs.k8s.io/yaml" "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/internal/adapter/slogdiag" "github.com/stacklok/mecatl/internal/app" ) @@ -119,7 +122,8 @@ func runActionScript(t *testing.T, action actionFile, with map[string]string) ([ step := action.Runs.Steps[idx] dir := t.TempDir() argsOut := filepath.Join(dir, "argv") - fake := "#!/bin/sh\nprintf '%s\\n' \"$@\" > \"$ARGS_OUT\"\n" + // NUL-separated, so a multi-line value (the default instructions) stays one arg. + fake := "#!/bin/sh\nprintf '%s\\0' \"$@\" > \"$ARGS_OUT\"\n" if err := os.WriteFile(filepath.Join(dir, "mecatequi"), []byte(fake), 0o700); err != nil { t.Fatal(err) } @@ -170,7 +174,7 @@ func runActionScript(t *testing.T, action actionFile, with map[string]string) ([ if rerr != nil { t.Fatalf("fake mecatequi was not invoked: %v\n%s", rerr, out) } - return strings.Split(strings.TrimRight(string(raw), "\n"), "\n"), string(out), nil + return strings.Split(strings.TrimSuffix(string(raw), "\x00"), "\x00"), string(out), nil } // hasPair reports whether argv carries flag immediately followed by value. @@ -183,12 +187,14 @@ func hasPair(argv []string, flag, value string) bool { return false } -// TestShippedAllowAllDefaultsDeclareCheckerChoice pins the checker declaration -// for the composite action and this repo's live workflow: whenever they run an -// allow-all mode they pass a checker model or the explicit --guardrails off, so -// the startup refusal never fires on a shipped default. It executes the action's -// real bash body against a fake binary rather than grepping it. -func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { +// hasGuardrailsFlag reports whether argv carries any guardrails checker flag. +func hasGuardrailsFlag(argv []string) bool { + return slices.ContainsFunc(argv, func(a string) bool { return strings.HasPrefix(a, "--guardrails") }) +} + +// loadAction parses the composite action, skipping when bash is unavailable. +func loadAction(t *testing.T) actionFile { + t.Helper() if _, err := exec.LookPath("bash"); err != nil { t.Skip("bash is required to execute the composite action body") } @@ -200,14 +206,109 @@ func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { if err := yaml.Unmarshal(raw, &action); err != nil { t.Fatalf("parse action.yml: %v", err) } + return action +} - t.Run("action defaults", func(t *testing.T) { +// buildFromActionArgv runs the action body with the given inputs against a fake +// binary, then feeds the argv it produced (plus extra flags, for example a +// mounted operator settings file) through the real CLI composition with the +// mock provider. The workspace input is pointed at a hermetic git repo. +func buildFromActionArgv(t *testing.T, action actionFile, with map[string]string, extra ...string) (*app.Built, error) { + t.Helper() + repo := t.TempDir() + initTestRepo(t, repo) + inputs := map[string]string{"workspace": repo} + for k, v := range with { + inputs[k] = v + } + argv, out, err := runActionScript(t, action, inputs) + if err != nil { + t.Fatalf("action body failed: %v\n%s", err, out) + } + f, err := parseFlags(append(argv, extra...)) + if err != nil { + t.Fatalf("parseFlags(%q): %v", argv, err) + } + cfg := appConfig(f, port.NopDiagnostics{}, observability{}) + cfg.UseMock, cfg.NoSoul = true, true + return buildIsolated(t, context.Background(), cfg) +} + +// TestOmittedGuardrailsInputInheritsSettingsChecker covers the default action +// input (no guardrails flag) composed with operator settings: a checker +// configured there lets auto start enforcing, and with none auto refuses. +func TestOmittedGuardrailsInputInheritsSettingsChecker(t *testing.T) { + action := loadAction(t) + for name, settings := range map[string]string{ + "guardrails model": "guardrails:\n model: mock-checker\n", + "guardrail slot": "models:\n slots:\n guardrail: mock-checker\n", + } { + t.Run(name, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(path, []byte(settings), 0o600); err != nil { + t.Fatal(err) + } + built, err := buildFromActionArgv(t, action, nil, "--permission-config", path) + if err != nil { + t.Fatalf("auto with an inherited %s checker must start: %v", name, err) + } + defer built.Close() + ctx := context.Background() + outcome, err := run(ctx, built.Service, session.Limits{}, "summarise the repo", io.Discard) + if err != nil { + t.Fatalf("run: %v", err) + } + sess, err := built.Service.GetSession(ctx, session.SessionID(outcome.Summary.SessionID)) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if sess.Mode != session.ModeAuto { + t.Fatalf("session mode = %q, want auto", sess.Mode) + } + }) + } + t.Run("no inherited checker refuses", func(t *testing.T) { + built, err := buildFromActionArgv(t, action, nil) + if err == nil { + built.Close() + t.Fatal("auto with no inherited checker must refuse to start") + } + if !strings.Contains(err.Error(), "requires an enforcing guardrails checker") { + t.Fatalf("refusal = %v, want the enforcing-checker error", err) + } + }) + t.Run("explicit off overrides the settings checker", func(t *testing.T) { + path := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(path, []byte("guardrails:\n model: mock-checker\n"), 0o600); err != nil { + t.Fatal(err) + } + built, err := buildFromActionArgv(t, action, map[string]string{"guardrails-model": "off"}, "--permission-config", path) + if err == nil { + built.Close() + t.Fatal("auto with the explicit kill-switch must refuse to start") + } + if !strings.Contains(err.Error(), "requires an enforcing guardrails checker") { + t.Fatalf("refusal = %v, want the enforcing-checker error", err) + } + }) +} + +// TestShippedAllowAllDefaultsDeclareCheckerChoice pins the tri-state checker +// input of the composite action and this repo's live workflow: an empty +// guardrails-model passes no flag (the binary inherits the settings checker), +// "off" passes the kill-switch, and any other value names the checker. It +// executes the action's real bash body against a fake binary rather than +// grepping it. +func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { + action := loadAction(t) + + t.Run("action defaults inherit the checker", func(t *testing.T) { argv, out, err := runActionScript(t, action, nil) if err != nil { t.Fatalf("action body failed: %v\n%s", err, out) } - if !hasPair(argv, "--permission-mode", "auto") || !hasPair(argv, "--guardrails", "off") || slices.Contains(argv, "--posture") { - t.Fatalf("default action argv = %q, want --permission-mode auto with --guardrails off and no --posture", argv) + if !hasPair(argv, "--permission-mode", "auto") || hasGuardrailsFlag(argv) || slices.Contains(argv, "--posture") { + t.Fatalf("default action argv = %q, want --permission-mode auto with no guardrails flag and no --posture", argv) } }) t.Run("checker model", func(t *testing.T) { @@ -219,13 +320,22 @@ func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { t.Fatalf("argv = %q, want --guardrails-model checker-model and no kill-switch", argv) } }) + t.Run("explicit off", func(t *testing.T) { + argv, out, err := runActionScript(t, action, map[string]string{"guardrails-model": "off"}) + if err != nil { + t.Fatalf("action body failed: %v\n%s", err, out) + } + if !hasPair(argv, "--guardrails", "off") || slices.Contains(argv, "--guardrails-model") { + t.Fatalf("argv = %q, want --guardrails off and no --guardrails-model", argv) + } + }) t.Run("deprecated posture input", func(t *testing.T) { argv, out, err := runActionScript(t, action, map[string]string{"posture": "auto"}) if err != nil { t.Fatalf("action body failed: %v\n%s", err, out) } - if !hasPair(argv, "--posture", "auto") || slices.Contains(argv, "--permission-mode") || !hasPair(argv, "--guardrails", "off") { - t.Fatalf("argv = %q, want the deprecated --posture auto alone with --guardrails off", argv) + if !hasPair(argv, "--posture", "auto") || slices.Contains(argv, "--permission-mode") || hasGuardrailsFlag(argv) { + t.Fatalf("argv = %q, want the deprecated --posture auto alone with no guardrails flag", argv) } if !strings.Contains(out, "::warning::") || !strings.Contains(out, "permission-mode") { t.Fatalf("deprecated posture input did not warn naming permission-mode: %s", out) @@ -263,15 +373,12 @@ func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { with[k] = fmt.Sprint(v) } } - argv, out, err := runActionScript(t, action, with) - if err != nil { - t.Fatalf("workflow inputs failed the action body: %v\n%s", err, out) - } - if !hasPair(argv, "--permission-mode", "auto") { - t.Fatalf("workflow argv = %q, want --permission-mode auto", argv) - } - if !hasPair(argv, "--guardrails", "off") && !slices.Contains(argv, "--guardrails-model") { - t.Fatalf("workflow runs allow-all without a checker choice: %q", argv) + // The live workflow mounts no operator settings, so its argv alone must + // start: the real composition, not a flag-shape check, decides. + if built, err := buildFromActionArgv(t, action, with); err != nil { + t.Fatalf("workflow inputs do not start mecatequi: %v", err) + } else { + built.Close() } } } diff --git a/cmd/mecatequi/run.go b/cmd/mecatequi/run.go index 15f134950f..b12f208d9d 100644 --- a/cmd/mecatequi/run.go +++ b/cmd/mecatequi/run.go @@ -162,8 +162,11 @@ type runOutcome struct { // filled from the Service's DefaultLimits inside CreateSession, so passing the zero // value preserves the deployment defaults, and passing only MaxTurns caps turns while // the tool-call / failure caps stay at their defaults (never silently disabled). +// +// The session mode is left unspecified so the Service's DefaultMode — the mode +// resolved from --permission-mode — applies. func run(ctx context.Context, svc *server.Service, limits session.Limits, prompt string, w io.Writer) (runOutcome, error) { - sess, err := svc.CreateSession(ctx, session.ModeDefault, limits) + sess, err := svc.CreateSession(ctx, "", limits) if err != nil { return runOutcome{}, fmt.Errorf("create session: %w", err) } diff --git a/cmd/mecatequi/run_test.go b/cmd/mecatequi/run_test.go index 1123132855..f47fc134d9 100644 --- a/cmd/mecatequi/run_test.go +++ b/cmd/mecatequi/run_test.go @@ -73,6 +73,51 @@ func gitInRepo(t *testing.T, dir string, args ...string) { } } +// TestRunUsesPermissionModeFromFlags drives the real CLI boundary — parseFlags, +// appConfig, app.Build, run — and proves the run's session starts in the mode +// --permission-mode selected rather than a hard-coded default. +func TestRunUsesPermissionModeFromFlags(t *testing.T) { + ctx := context.Background() + for token, want := range map[string]session.PermissionMode{ + "plan": session.ModePlan, + "default": session.ModeDefault, + "accept-edits": session.ModeAccept, + "yolo": session.ModeYolo, + } { + t.Run(token, func(t *testing.T) { + repo := t.TempDir() + initTestRepo(t, repo) + args := []string{"--prompt", "x", "--workspace", repo, "--permission-mode", token} + if token == "yolo" { + args = append(args, "--guardrails", "off") + } + f, err := parseFlags(args) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + cfg := appConfig(f, port.NopDiagnostics{}, observability{}) + cfg.UseMock, cfg.NoSoul = true, true + built, err := buildIsolated(t, ctx, cfg) + if err != nil { + t.Fatalf("app.Build: %v", err) + } + defer built.Close() + var human bytes.Buffer + outcome, err := run(ctx, built.Service, session.Limits{}, "summarise the repo", &human) + if err != nil { + t.Fatalf("run: %v", err) + } + sess, err := built.Service.GetSession(ctx, session.SessionID(outcome.Summary.SessionID)) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if sess.Mode != want { + t.Fatalf("--permission-mode %s ran in session mode %q, want %q", token, sess.Mode, want) + } + }) + } +} + // TestRunEndToEndMockProvider is the model-facing e2e: a full app.Build over a // hermetic git repo with UseMock, then run() against the real Service. It asserts the // run completes cleanly (end_turn), leaves no diff, carries a usage struct, writes a diff --git a/cmd/mecatui/client/capabilities.go b/cmd/mecatui/client/capabilities.go index 29d3f58cec..cd8cf5e7be 100644 --- a/cmd/mecatui/client/capabilities.go +++ b/cmd/mecatui/client/capabilities.go @@ -49,6 +49,9 @@ type Capabilities struct { // ProjectTrust is "trusted" or "untrusted" for the server's launch // workspace, CHROME ONLY: the ui's header badge. Empty on an older server. ProjectTrust string + // SubagentAskReviewer is the server's subagent ask reviewer state ("on", + // "off", "inert"), CHROME ONLY: shown by /posture. Empty on an older server. + SubagentAskReviewer string // Worktrees is true when a WorktreeLister is wired (ListWorktrees may return a // non-empty list for a real git repo). It gates the /worktrees overlay — the // first-class operator workflow for binding a session to an EXISTING sibling @@ -133,6 +136,7 @@ func capabilitiesFrom(c *mecatlv1.ServerCapabilities) Capabilities { Audio: c.GetAudio(), Posture: c.GetPosture(), ProjectTrust: projectTrustFrom(c), + SubagentAskReviewer: c.GetSubagentAskReviewer(), Worktrees: c.GetWorktrees(), Scheduling: c.GetScheduling(), Reflection: c.GetReflection(), diff --git a/cmd/mecatui/client/capabilities_test.go b/cmd/mecatui/client/capabilities_test.go index 968d503fe4..548930f6c3 100644 --- a/cmd/mecatui/client/capabilities_test.go +++ b/cmd/mecatui/client/capabilities_test.go @@ -78,6 +78,11 @@ func TestCapabilitiesFrom(t *testing.T) { in: &mecatlv1.ServerCapabilities{ManualCompaction: true}, want: Capabilities{ManualCompaction: true}, }, + { + name: "subagent_ask_reviewer maps independently", + in: &mecatlv1.ServerCapabilities{SubagentAskReviewer: new("inert")}, + want: Capabilities{SubagentAskReviewer: "inert"}, + }, { name: "model_selection maps independently", in: &mecatlv1.ServerCapabilities{ModelSelection: true}, diff --git a/cmd/mecatui/config.go b/cmd/mecatui/config.go index 4ee2caea4a..b3e09ed3f8 100644 --- a/cmd/mecatui/config.go +++ b/cmd/mecatui/config.go @@ -398,7 +398,7 @@ func parseTransportFlags(mode transportMode, out io.Writer, args []string, brows fs.StringVar(&cfg.workspace, "workspace", "", "embedded server only: absolute deployment workspace root (default: cwd); not accepted by connect") registerMicroVMDevelopmentFlags(fs, &cfg.microVMDevRelease, &cfg.microVMDevAcknowledge) fs.StringVar(&cfg.mode, "mode", "default", "deprecated, use --permission-mode: start sessions in permission mode: default, plan, or accept-edits") - fs.StringVar(&cfg.permissionMode, "permission-mode", "", "set the permission mode: "+strings.Join(app.PermissionModeNames(), ", ")+"; the posture half is process-wide for the embedded server, the session half is only the default for new sessions") + fs.StringVar(&cfg.permissionMode, "permission-mode", "", "set the permission mode: "+strings.Join(app.PermissionModeNames(), ", ")+"; sets the mode new sessions start in and, for the embedded server, the most permissive mode a session may switch to. It never grants project trust; use --trust-project") fs.Func("debug-mcp", "attach configured streaming-HTTP MCP server NAME to debug sessions (repeatable)", func(value string) error { cfg.debugMCP = append(cfg.debugMCP, value) return nil diff --git a/cmd/mecatui/customization/defaults.go b/cmd/mecatui/customization/defaults.go index 0071fc5c15..daa20794ee 100644 --- a/cmd/mecatui/customization/defaults.go +++ b/cmd/mecatui/customization/defaults.go @@ -3,7 +3,7 @@ package customization // modeSegmentTemplate is the header's permission-mode segment. The yolo mode is // marked with the alarm pill (the danger token, its text carrying the pill's // padding), preceded by a ⚡️ bolt outside the pill on an emoji-capable -// terminal; every other mode, including a pending or blocked yolo, is plain +// terminal; every other mode, including a pending yolo, is plain // warning text. const modeSegmentTemplate = `{{if .Session.Mode}} · mode {{if eq .Session.Mode "yolo"}}{{if .Terminal.Emoji}}⚡️ {{end}} YOLO {{else}}{{.Session.Mode}}{{end}}{{end}}` diff --git a/cmd/mecatui/permission_mode.go b/cmd/mecatui/permission_mode.go index ea22dfd2c2..303ecae370 100644 --- a/cmd/mecatui/permission_mode.go +++ b/cmd/mecatui/permission_mode.go @@ -115,20 +115,8 @@ func deprecatedPermissionFlagWarnings(c config) []string { hint := "no single token names this combination; it still resolves as before" posture := app.ResolveAliasPosture(app.ParsePosture(c.posture), c.allowAllTools, c.trustProject) if !c.modeFlagSet { - // No explicit session mode: look up the replacement token by posture alone. - // auto and yolo have their own session modes (ModeAuto/ModeYolo); the - // strict-posture tiers use ModeDefault. PermissionModeForPair with ModeDefault - // would miss auto and yolo since their tokens now use their own modes. - switch posture { - case app.PostureAuto: - hint = "use --permission-mode auto" - case app.PostureYolo: - hint = "use --permission-mode yolo" - default: - if tok, ok := app.PermissionModeForPair(posture, session.ModeDefault); ok { - hint = "use --permission-mode " + tok.Name - } - } + // No explicit session mode: the replacement token by posture alone. + hint = "use --permission-mode " + app.PostureReplacementToken(posture) } else { mode := c.mode if tok, ok := app.PermissionModeForPair(posture, sessionModeFromTUI(mode)); ok { diff --git a/cmd/mecatui/ui/builtins.go b/cmd/mecatui/ui/builtins.go index 6335ccb2f4..ef9ed9d59c 100644 --- a/cmd/mecatui/ui/builtins.go +++ b/cmd/mecatui/ui/builtins.go @@ -587,7 +587,7 @@ func (m Model) runLearningSensitivity() (tea.Model, tea.Cmd) { // non-empty. The summary names the four defenses the posture controls so an operator // can confirm, e.g., that the child prompt-injection defense is OFF under yolo. func (m Model) runPosture() (tea.Model, tea.Cmd) { - base := postureSummary(m.caps.Posture, m.caps.ProjectTrust) + base := postureSummary(m.caps.Posture, m.caps.ProjectTrust, m.caps.SubagentAskReviewer) if m.deps.Guardrails == nil || m.sessionID == "" { m.statusMsg = m.deps.Theme.Style("muted").Render(base + "; checker unknown (server does not expose guardrail coverage)") return m, nil @@ -646,8 +646,9 @@ func (m Model) runDebugAsk() (tea.Model, tea.Cmd) { // description names the ceiling rather than claiming allow-all is always on. // Project-trust is the server-reported trust when known (trust), else inferred // from the posture, which raises it for trusted+ on interactive roots. An -// empty/unknown token degrades to a bare label. -func postureSummary(p, projectTrust string) string { +// empty/unknown token degrades to a bare label. The subagent ask reviewer is +// named only when the server reported it. +func postureSummary(p, projectTrust, reviewer string) string { ceilingAuto := p == postureAuto ceilingYolo := p == postureYolo childDefenseOff := p == postureYolo // yolo session mode loosens child substitution @@ -675,7 +676,27 @@ func postureSummary(p, projectTrust string) string { " — ceiling " + ceiling + "; child $()/heredoc auto-run when in yolo mode (injection-defense off) " + onoff(childDefenseOff) + "; project-trust " + onoff(trust) + - " (allow-all is mode-driven: auto/yolo sessions inject it; Deny & configured Ask always apply)" + " (allow-all is mode-driven: auto/yolo sessions inject it; Deny & configured Ask always apply)" + + reviewerSummary(reviewer) +} + +// reviewerSummary renders the /posture segment for the server-reported subagent +// ask reviewer state. Empty (an older server) renders nothing; an unrecognized +// value is never echoed raw. +func reviewerSummary(state string) string { + const prefix = "; subagent ask reviewer " + switch state { + case "": + return "" + case "on": + return prefix + "on (a model may approve subagent permission requests no human can answer)" + case "off": + return prefix + "off" + case "inert": + return prefix + "inert (configured, but you answer subagent permission requests)" + default: + return prefix + unknownLabel + } } type builtinName struct { diff --git a/cmd/mecatui/ui/help.go b/cmd/mecatui/ui/help.go index 4749cf0922..b94c2100d0 100644 --- a/cmd/mecatui/ui/help.go +++ b/cmd/mecatui/ui/help.go @@ -323,9 +323,7 @@ type PermissionModeEntry struct { // cannot import the composition layer, so this is a display copy; a test in the // mecatui main package pins it to app.ParsePermissionMode so the two never drift. func PermissionModeVocabulary() []PermissionModeEntry { - // 5-token vocabulary (trusted and trusted-accept-edits removed; auto and yolo - // now have their own session modes ModeAuto/ModeYolo, which the proto wire and - // TUI render as "default" via ModeString(ModeFromString(...))). + // auto and yolo each have their own session mode on the wire. return []PermissionModeEntry{ {Name: "plan", Posture: postureStrict, SessionMode: "plan"}, {Name: "default", Posture: postureStrict, SessionMode: client.ModeDefaultString}, @@ -350,9 +348,9 @@ func writeHelpPermissionModes(b *strings.Builder, th theme.Theme, hk helpKeys, e writeHelpBodyLines(b, th, "The posture half applies to the whole server and is fixed when it starts.", "The session half is only the default for new sessions.", - hk.modeSwitch+" cycles every mode. A mode that raises the posture needs a restart, and auto or yolo a guardrails checker;", - "cycling marks it blocked and holds prompts until you press "+hk.cancel+" to return or move on.", - "A mode below the posture applies its session half; the posture stays.", + hk.modeSwitch+" cycles every mode. A mode that raises the posture needs a restart, and auto also an enforcing guardrails checker;", + "cycling onto one keeps the current mode and your draft, and the footer says what makes it available.", + "A mode at or below the posture applies its session half live.", ) if embedded { writeHelpBodyLines(b, th, diff --git a/cmd/mecatui/ui/keys.go b/cmd/mecatui/ui/keys.go index b032f7b6a8..8159590e83 100644 --- a/cmd/mecatui/ui/keys.go +++ b/cmd/mecatui/ui/keys.go @@ -64,8 +64,8 @@ type keyMap struct { ScrollBottom key.Binding // ModeSwitch (shift+tab) cycles every permission mode: default → plan → - // accept-edits → trusted → trusted-accept-edits → auto → yolo → default (see - // cycleMode for modes that need a restart). Unlike Alt+M, Shift+Tab does not depend on a terminal + // accept-edits → auto → yolo → default (see cycleMode for modes above the + // server ceiling). Unlike Alt+M, Shift+Tab does not depend on a terminal // mapping macOS Option to Meta, and it never collides with prose input. ModeSwitch key.Binding diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go index 4c39a33b1c..c20079dfb4 100644 --- a/cmd/mecatui/ui/mode_cycle.go +++ b/cmd/mecatui/ui/mode_cycle.go @@ -1,11 +1,7 @@ package ui import ( - "strings" - - "charm.land/bubbles/v2/key" tea "charm.land/bubbletea/v2" - "charm.land/lipgloss/v2" ) // modeCycleOrder is the ModeSwitch order over every permission mode: the @@ -88,9 +84,11 @@ func nextModeToken(cur string) string { } // cycleMode lands on the next permission mode. A mode whose posture is at or -// below the running one applies its session half live; one that would raise the -// posture cannot, because the posture is fixed when the server starts, so the -// cycle stops on it and says what to configure and restart. +// below the running one applies its session half live. One that would raise the +// posture cannot apply, because the posture (the server ceiling) is fixed when +// the server starts: the cycle only parks its cursor there so the next press +// moves on, while the session keeps its confirmed mode, the draft stays usable, +// and the footer says what would make the mode available. func (m Model) cycleMode() (tea.Model, tea.Cmd) { cur := m.currentModeToken() if m.modeRefused != "" { @@ -99,7 +97,7 @@ func (m Model) cycleMode() (tea.Model, tea.Cmd) { next := permissionModeEntry(nextModeToken(cur)) if postureRank(next.Posture) > postureRank(m.caps.Posture) { m.modeCursor = modeCursor{token: next.Name, session: m.desiredMode()} - m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeBlockedStatus()) + m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeUnavailableStatus(next)) (&m).relayout() return m, nil } @@ -110,8 +108,9 @@ func (m Model) cycleMode() (tea.Model, tea.Cmd) { return m, cmd } -// headerMode is the session mode the header shows: the mode the cycle landed -// on when it did, else the session's mode, marked blocked or pending. +// headerMode is the session mode the header shows: the confirmed mode, or the +// requested one marked pending. A mode the cycle parked on because it is +// unavailable never shows here: the session is not running it. // // "pending" means a SetMode round-trip is in flight. When the pending mode // equals the server-confirmed active mode (m.pendingMode == m.activeMode) the @@ -127,86 +126,21 @@ func (m Model) headerMode() string { } if m.pendingMode != "" { mode = m.pendingMode - } - if m.modeCursor.token != "" && m.modeCursor.session == m.desiredMode() { - mode = m.modeCursor.token - } - switch { - case m.modeBlocked(): - mode += modeBlockedSuffix - case m.pendingMode != "" && m.pendingMode != m.activeMode: - // Only show "pending" when the in-flight mode differs from what the - // server has already confirmed — a genuine transition, not a no-op. - mode += " pending" + if m.pendingMode != m.activeMode { + // Only show "pending" when the in-flight mode differs from what the + // server has already confirmed — a genuine transition, not a no-op. + mode += " pending" + } } return mode } -// modeBlocked reports that the cycle sits on a mode that needs a restart. The -// session keeps running its accepted mode, but prompts and edits are held so -// nothing is sent under a mode the operator did not mean. -func (m Model) modeBlocked() bool { - e := permissionModeEntry(m.currentModeToken()) - return e.Name != "" && postureRank(e.Posture) > postureRank(m.caps.Posture) -} - -func (m Model) modeEscapeHint() string { - return firstKey(m.keys.Cancel, "esc") + " back to " + m.acceptedModeToken() + " · " + - firstKey(m.keys.ModeSwitch, "shift+tab") + " next mode" -} - -func (m Model) modeBlockedStatus() string { - return "mode " + m.currentModeToken() + " is blocked — " + m.modeEscapeHint() -} - -// leaveBlockedMode is the escape hatch: drop the cursor so the session's -// accepted mode is the current one again. -func (m Model) leaveBlockedMode() Model { - m.modeCursor = modeCursor{} - m.statusMsg = m.deps.Theme.Style("success").Render("mode " + m.acceptedModeToken()) - (&m).relayout() - return m -} - -// onModeBlockedKey holds the prompt while the cycle sits on a blocked mode. Esc -// returns to the accepted mode; the mode switch, scrolling, help, and (at idle) -// the read-only panels still work; every key that would edit or send the draft -// is swallowed with a reminder. The draft itself is kept untouched. -func (m Model) onModeBlockedKey(msg tea.KeyPressMsg) (Model, bool) { - if !m.modeBlocked() || (m.phase != phaseIdle && m.phase != phaseRunning) { - return m, false - } - switch { - case key.Matches(msg, m.keys.Cancel): - return m.leaveBlockedMode(), true - case key.Matches(msg, m.keys.Help): - opened, _ := m.runHelp() - return opened.(Model), true - case key.Matches(msg, m.keys.ModeSwitch), key.Matches(msg, m.keys.CopySelection), - key.Matches(msg, m.keys.ScrollU), key.Matches(msg, m.keys.ScrollD), - key.Matches(msg, m.keys.ScrollTop), key.Matches(msg, m.keys.ScrollBottom): - return m, false - case m.phase == phaseIdle && (key.Matches(msg, m.keys.Agents) || key.Matches(msg, m.keys.MCPPanel) || - key.Matches(msg, m.keys.Resources) || key.Matches(msg, m.keys.Prompts) || key.Matches(msg, m.keys.Effort)): - return m, false - } - m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeBlockedStatus()) - return m, true -} - -// renderModeBlocked replaces the prompt while the mode is blocked: why the mode -// cannot apply, what makes it apply, and how to get back. -func (m Model) renderModeBlocked() string { - th := m.deps.Theme - style := inputRailStyle(th, m.inputMode()) - contentW := max(1, m.width-style.GetHorizontalFrameSize()) - wrap := lipgloss.NewStyle().Width(contentW).Background(th.Color("bgPanel")) - lines := []string{ - wrap.Inherit(th.Style("warning")).Bold(true).Render("⚠ mode " + m.currentModeToken() + " is blocked: prompts and edits are paused, your draft is kept"), - wrap.Inherit(th.Style("text")).Render(m.modeRestartHint(permissionModeEntry(m.currentModeToken()))), - wrap.Inherit(th.Style("muted")).Render(m.modeEscapeHint()), - } - return style.Render(strings.Join(lines, "\n")) +// modeUnavailableStatus is the footer notice for a mode above the server +// ceiling: the session stays in its confirmed mode, what would make the mode +// available, and that the next press moves on. +func (m Model) modeUnavailableStatus(e PermissionModeEntry) string { + return "mode " + e.Name + " unavailable, staying in " + m.acceptedModeToken() + " — " + + m.modeRestartHint(e) + " · " + firstKey(m.keys.ModeSwitch, "shift+tab") + " next mode" } // modeLabel names a landed mode for the footer. All modes at or below the @@ -217,18 +151,30 @@ func (Model) modeLabel(e PermissionModeEntry) string { return e.Name } -// modeRestartHint says why a mode cannot apply now and what makes it apply. +// modeRestartHint says what makes a mode above the server ceiling available: a +// restart with a higher --permission-mode and, for auto only, an enforcing +// guardrails checker on the server. func (m Model) modeRestartHint(e PermissionModeEntry) string { - checker := postureRank(e.Posture) >= postureRank(postureAuto) + checker := e.Posture == postureAuto if !m.deps.Embedded { - hint := e.Name + " is fixed by the remote server: its operator must restart mecated with --permission-mode " + e.Name + hint := "the remote server's operator must restart mecated with --permission-mode " + e.Name if checker { - hint += " and a guardrails checker" + hint += " and an enforcing guardrails checker" } return hint } + hint := "quit and relaunch with mecatui --permission-mode " + e.Name if checker { - return e.Name + " needs a guardrails checker and a restart: set guardrails.model in settings.yaml, then relaunch with mecatui --permission-mode " + e.Name + hint += "; auto also needs an enforcing guardrails checker (set guardrails.model in settings.yaml)" + } + return hint +} + +// modeRefusedHint adds what the server needs before it accepts a refused mode. +// Only auto has a prerequisite beyond the ceiling. +func modeRefusedHint(mode string) string { + if mode == "auto" { + return " — auto needs an enforcing guardrails checker on the server" } - return e.Name + " needs a restart: quit and relaunch with mecatui --permission-mode " + e.Name + return "" } diff --git a/cmd/mecatui/ui/mode_test.go b/cmd/mecatui/ui/mode_test.go index 4bc7ff7448..a2771c99ff 100644 --- a/cmd/mecatui/ui/mode_test.go +++ b/cmd/mecatui/ui/mode_test.go @@ -172,9 +172,18 @@ func TestRefusedModeDoesNotTrapCycle(t *testing.T) { } conv.setModeErr = errors.New(`mode "auto" requires an enforcing guardrails checker`) press() - if m.activeMode != "accept-edits" || !strings.Contains(stripANSIstr(m.statusMsg), "mode auto refused") { - t.Fatalf("after auto refusal: active=%q status=%q", m.activeMode, stripANSIstr(m.statusMsg)) + status := stripANSIstr(m.statusMsg) + if m.activeMode != "accept-edits" || m.headerMode() != "accept-edits" || + !strings.Contains(status, "mode auto refused, staying in accept-edits") || + !strings.Contains(status, "auto needs an enforcing guardrails checker on the server") { + t.Fatalf("after auto refusal: active=%q header=%q status=%q", m.activeMode, m.headerMode(), status) + } + // The refusal freezes nothing: the draft stays editable. + m = applyAll(m, tea.KeyPressMsg{Code: 'x', Text: "x"}) + if got := m.prompt.Value(); got != "x" { + t.Fatalf("prompt after refusal = %q, want editable", got) } + m.prompt.Rewrite("") conv.setModeErr = nil press() if got := conv.setModes(); len(got) != 2 || got[1] != "yolo" { diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index 89f09721aa..79c8fa714c 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -48,21 +48,21 @@ func pressModeSwitch(t *testing.T, m Model) (Model, bool) { return applyAll(m, cmd()), true } -// modeCycleStep is one ModeSwitch press: the mode it lands on, whether it -// applies a session half (issues SetMode) or is blocked pending a restart, and -// phrases the footer status or the input area must carry. +// modeCycleStep is one ModeSwitch press: the mode the cycle cursor lands on, +// whether it applies a session half (issues SetMode), and phrases the footer +// status must carry. stays is set when the mode is unavailable (above the server +// ceiling): the confirmed mode the header must keep showing. type modeCycleStep struct { token string setMode bool - blocked bool + stays string status []string } -// visibleModeText is the footer status plus the input area, with wrapping and -// the rail border collapsed so a phrase can be matched across a wrapped line. +// visibleModeText is the footer status with wrapping collapsed so a phrase can +// be matched across a wrapped line. func visibleModeText(m Model) string { - input := strings.ReplaceAll(stripANSIstr(m.renderInput()), "│", " ") - return strings.Join(strings.Fields(stripANSIstr(m.statusMsg)+" "+input), " ") + return strings.Join(strings.Fields(stripANSIstr(m.statusMsg)), " ") } func runModeCycle(t *testing.T, m Model, steps []modeCycleStep) Model { @@ -76,20 +76,23 @@ func runModeCycle(t *testing.T, m Model, steps []modeCycleStep) Model { if got := m.currentModeToken(); got != s.token { t.Fatalf("step %d: landed on %q, want %q", i, got, s.token) } - if got := m.modeBlocked(); got != s.blocked { - t.Fatalf("step %d (%s): blocked = %v, want %v", i, s.token, got, s.blocked) - } wantHeader := s.token - if s.blocked { - wantHeader += " blocked" + if s.stays != "" { + wantHeader = s.stays } if got := statusMode(m); got != wantHeader { t.Fatalf("step %d: header mode = %q, want %q", i, got, wantHeader) } text := visibleModeText(m) + if s.stays != "" { + want := "mode " + s.token + " unavailable, staying in " + s.stays + if !strings.Contains(text, want) { + t.Fatalf("step %d (%s): status %q missing %q", i, s.token, text, want) + } + } for _, want := range s.status { if !strings.Contains(text, want) { - t.Fatalf("step %d (%s): visible text %q missing %q", i, s.token, text, want) + t.Fatalf("step %d (%s): status %q missing %q", i, s.token, text, want) } } } @@ -105,8 +108,8 @@ func TestModeSwitchCyclesEveryMode(t *testing.T) { m = runModeCycle(t, m, []modeCycleStep{ {token: "plan", setMode: true, status: []string{"mode plan"}}, {token: "accept-edits", setMode: true, status: []string{"mode accept-edits"}}, - {token: "auto", blocked: true, status: []string{"guardrails checker", "guardrails.model", "mecatui --permission-mode auto", "prompts and edits are paused"}}, - {token: "yolo", blocked: true, status: []string{"guardrails checker", "mecatui --permission-mode yolo"}}, + {token: "auto", stays: "accept-edits", status: []string{"enforcing guardrails checker", "guardrails.model", "mecatui --permission-mode auto", "shift+tab next mode"}}, + {token: "yolo", stays: "accept-edits", status: []string{"mecatui --permission-mode yolo"}}, {token: "default", setMode: true, status: []string{"mode default"}}, {token: "plan", setMode: true}, }) @@ -122,7 +125,7 @@ func TestModeSwitchCyclesEveryMode(t *testing.T) { // TestModeSwitchUnderTrustedPosture pins that a server running with the legacy // trusted posture (reachable via deprecated --posture trusted) handles the // 5-token vocabulary correctly: strict-posture tokens apply their session half, -// posture-raising tokens (auto, yolo) are blocked. +// posture-raising tokens (auto, yolo) are unavailable. // Since "trusted" is no longer a named token, the start position is the session // mode itself ("default"), and cycling visits all five tokens. func TestModeSwitchUnderTrustedPosture(t *testing.T) { @@ -136,9 +139,9 @@ func TestModeSwitchUnderTrustedPosture(t *testing.T) { runModeCycle(t, m, []modeCycleStep{ {token: "plan", setMode: true}, {token: "accept-edits", setMode: true}, - // auto and yolo raise posture above trusted → blocked (need restart). - {token: "auto", blocked: true, status: []string{"auto needs a guardrails checker", "esc back to accept-edits"}}, - {token: "yolo", blocked: true, status: []string{"yolo needs a guardrails checker"}}, + // auto and yolo raise posture above trusted → unavailable (need restart). + {token: "auto", stays: "accept-edits", status: []string{"auto also needs an enforcing guardrails checker"}}, + {token: "yolo", stays: "accept-edits", status: []string{"mecatui --permission-mode yolo"}}, // In the new architecture, switching to a lower-ceiling mode is fully effective: // the session mode drives allow-all, so "posture stays" no longer applies. {token: "default", setMode: true, status: []string{"mode default"}}, @@ -157,8 +160,8 @@ func TestModeSwitchConnectNamesServerRestart(t *testing.T) { m := permissionModeTestModel(t, conv, postureStrict, false) m.activeMode = "accept-edits" m = runModeCycle(t, m, []modeCycleStep{ - {token: "auto", blocked: true, status: []string{"--permission-mode auto and a guardrails checker"}}, - {token: "yolo", blocked: true, status: []string{"remote server"}}, + {token: "auto", stays: "accept-edits", status: []string{"remote server's operator must restart mecated with --permission-mode auto and an enforcing guardrails checker"}}, + {token: "yolo", stays: "accept-edits", status: []string{"remote server's operator must restart mecated with --permission-mode yolo"}}, }) if text := visibleModeText(m); strings.Contains(text, "mecatui --permission-mode") { t.Fatalf("connect hint offers a local relaunch: %q", text) @@ -168,11 +171,11 @@ func TestModeSwitchConnectNamesServerRestart(t *testing.T) { } } -// TestBlockedModeHoldsPromptUntilEscape pins that landing on a mode that needs -// a restart holds the prompt: typing, enter, and paste neither edit nor send the -// draft, at idle or mid-run, and esc returns to the accepted mode with the draft -// intact rather than cancelling the run. -func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { +// TestUnavailableModeKeepsComposerUsable pins that landing on a mode above the +// server ceiling freezes nothing: at idle or mid-run, typing and paste still edit +// the draft, the input area still shows it, enter still reaches the send/queue +// path, the header keeps the confirmed mode, and the next press moves on. +func TestUnavailableModeKeepsComposerUsable(t *testing.T) { for _, phase := range []phase{phaseIdle, phaseRunning} { t.Run(fmt.Sprint(phase), func(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} @@ -181,48 +184,28 @@ func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { m = runModeCycle(t, m, []modeCycleStep{ {token: "plan", setMode: true}, {token: "accept-edits", setMode: true}, - {token: "auto", blocked: true}, + {token: "auto", stays: "accept-edits"}, }) - m.phase = phaseRunning - if phase == phaseIdle { - m.phase = phaseIdle - } - for _, msg := range []tea.Msg{ - tea.KeyPressMsg{Code: 'x', Text: "x"}, - tea.KeyPressMsg{Code: tea.KeyEnter}, - tea.PasteMsg{Content: "pasted"}, - } { - mm, cmd := m.Update(msg) - m = mm.(Model) - if cmd != nil { - t.Fatalf("%T while blocked issued a command", msg) - } - } - if got := m.prompt.Value(); got != "keep this draft" { - t.Fatalf("blocked prompt changed to %q", got) + m.phase = phase + + m = applyAll(m, tea.KeyPressMsg{Code: 'x', Text: "x"}, tea.PasteMsg{Content: " pasted"}) + if got := m.prompt.Value(); got != "keep this draftx pasted" { + t.Fatalf("prompt = %q, want typing and paste to reach the composer", got) } - if len(m.queued) != 0 || m.phase != phase { - t.Fatalf("blocked enter queued %v / moved phase to %v", m.queued, m.phase) + if !strings.Contains(stripANSIstr(m.renderInput()), "keep this draftx pasted") { + t.Fatalf("input area does not show the draft: %q", stripANSIstr(m.renderInput())) } - if text := visibleModeText(m); !strings.Contains(text, "mode auto is blocked") || strings.Contains(stripANSIstr(m.renderInput()), "keep this draft") { - t.Fatalf("blocked input area = %q", text) + if got := statusMode(m); got != "accept-edits" { + t.Fatalf("header mode = %q, want the confirmed accept-edits", got) } - mm, cmd := m.Update(tea.KeyPressMsg{Code: tea.KeyEscape}) + mm, cmd := m.Update(tea.KeyPressMsg{Code: tea.KeyEnter}) m = mm.(Model) - if cmd != nil || strings.Contains(stripANSIstr(m.statusMsg), "cancelling") { - t.Fatalf("esc while blocked must only leave the mode, status %q", stripANSIstr(m.statusMsg)) - } - if m.modeBlocked() || statusMode(m) != "accept-edits" { - t.Fatalf("after esc: blocked=%v header=%q, want accept-edits", m.modeBlocked(), statusMode(m)) - } - if !strings.Contains(stripANSIstr(m.renderInput()), "keep this draft") { - t.Fatal("draft not shown again after esc") - } - m = applyAll(m, tea.KeyPressMsg{Code: '!', Text: "!"}) - if got := m.prompt.Value(); got != "keep this draft!" { - t.Fatalf("prompt after esc = %q, want editable again", got) + if m.prompt.Value() != "" || (cmd == nil && len(m.queued) == 0) { + t.Fatalf("enter did not send or queue the draft: prompt=%q queued=%v cmd=%v", m.prompt.Value(), m.queued, cmd != nil) } + + m = runModeCycle(t, m, []modeCycleStep{{token: "yolo", stays: "accept-edits"}}) if got := conv.setModes(); strings.Join(got, ",") != "plan,accept-edits" { t.Fatalf("SetMode calls = %v, want only the two applied modes", got) } @@ -230,24 +213,45 @@ func TestBlockedModeHoldsPromptUntilEscape(t *testing.T) { } } -// TestBlockedModeHoldsQueuedPrompt pins that a run ending while the mode is -// blocked does not auto-send the queued follow-up. -func TestBlockedModeHoldsQueuedPrompt(t *testing.T) { +// TestUnavailableModeDoesNotHoldQueuedPrompt pins that a run ending while the +// cycle sits on an unavailable mode still auto-sends the queued follow-up. +func TestUnavailableModeDoesNotHoldQueuedPrompt(t *testing.T) { conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} m := permissionModeTestModel(t, conv, postureStrict, true) m = runModeCycle(t, m, []modeCycleStep{ {token: "plan", setMode: true}, {token: "accept-edits", setMode: true}, - {token: "auto", blocked: true}, + {token: "auto", stays: "accept-edits"}, }) m.queued = []string{"queued follow-up"} mm, cmd := m.drainQueue("end_turn") m = mm.(Model) - if cmd != nil || m.queuePaused != "mode" { - t.Fatalf("drain while blocked: cmd=%v paused=%q, want held", cmd != nil, m.queuePaused) + if cmd == nil || m.queuePaused != "" || m.phase != phaseRunning { + t.Fatalf("drain: cmd=%v paused=%q phase=%v, want the follow-up sent", cmd != nil, m.queuePaused, m.phase) } - if got := m.prompt.Value(); got != "/queue queued follow-up" { - t.Fatalf("held queue text = %q", got) +} + +// TestUnavailableModeHintNamesCheckerOnlyForAuto pins that only auto's +// unavailable hint mentions the guardrails checker; yolo needs only the restart. +func TestUnavailableModeHintNamesCheckerOnlyForAuto(t *testing.T) { + for _, embedded := range []bool{true, false} { + t.Run(fmt.Sprintf("embedded=%v", embedded), func(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "accept-edits"} + m := permissionModeTestModel(t, conv, postureStrict, embedded) + m.activeMode = "accept-edits" + m, _ = pressModeSwitch(t, m) + if auto := visibleModeText(m); !strings.Contains(auto, "mode auto unavailable") || !strings.Contains(auto, "guardrails checker") { + t.Fatalf("auto hint = %q, want it to name the guardrails checker", auto) + } + m, _ = pressModeSwitch(t, m) + yolo := visibleModeText(m) + if !strings.Contains(yolo, "mode yolo unavailable") || !strings.Contains(yolo, "--permission-mode yolo") { + t.Fatalf("yolo hint = %q, want the restart with --permission-mode yolo", yolo) + } + if strings.Contains(yolo, "checker") || strings.Contains(yolo, "guardrails") { + t.Fatalf("yolo hint = %q, must not mention a guardrails checker", yolo) + } + }) } } @@ -261,7 +265,6 @@ func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { body := stripANSIstr(m.helpBody()) // The token table, written out independently of PermissionModeVocabulary. - // 5-token vocabulary: trusted and trusted-accept-edits removed. // auto and yolo sessions start in their own named modes, not "default". want := []struct{ token, posture, session string }{ {"plan", "strict", "plan"}, @@ -289,12 +292,19 @@ func TestHelpOverlayShowsVocabularyAndScopeSplit(t *testing.T) { "The posture half applies to the whole server and is fixed when it starts.", "The session half is only the default for new sessions.", m.helpKeyMarkings().modeSwitch + " cycles every mode. A mode that raises the posture needs a restart", + "and auto also an enforcing guardrails checker", + "keeps the current mode and your draft", "mecatui --permission-mode ", } { if !strings.Contains(body, phrase) { t.Errorf("help overlay missing %q", phrase) } } + for _, stale := range []string{"auto or yolo", "blocked", "holds prompts", "trusted-accept-edits"} { + if strings.Contains(body, stale) { + t.Errorf("help overlay carries stale %q", stale) + } + } } // TestHeaderShowsModeNotPosture pins that the header shows the session mode and @@ -322,12 +332,12 @@ func TestHeaderShowsModeNotPosture(t *testing.T) { } // TestHeaderKeepsPostureAcrossModeCycle pins that under auto, cycling through -// yolo (blocked: above the auto ceiling), then through lower modes keeps the +// yolo (unavailable: above the auto ceiling), then through lower modes keeps the // trust badge on every frame, including the pending frames before the server // confirms each switch. // // A session on an auto-posture server starts in "auto" mode. The cycle order -// from "auto" is: yolo (blocked) → default → plan → accept-edits → auto → … +// from "auto" is: yolo (unavailable) → default → plan → accept-edits → auto → … // Yolo is the only mode that needs a restart; every other landing sends a // SetMode and shows "pending" until the server confirms. func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { @@ -358,13 +368,14 @@ func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { } assertAuto("start", "auto") - // yolo is above the auto ceiling → blocked, no server round trip. + // yolo is above the auto ceiling → unavailable, no server round trip, and + // the header keeps the confirmed auto. mm, cmd := m.Update(modeKey()) m = mm.(Model) if cmd != nil { - t.Fatalf("landing on yolo issued a command: should be blocked, not switched") + t.Fatalf("landing on yolo issued a command: should be unavailable, not switched") } - assertAuto("landed yolo", "yolo blocked") + assertAuto("landed yolo", "auto") // Switching to modes below auto (default, plan, accept-edits) all require // a SetMode round trip: the session is in "auto", switching to anything lower diff --git a/cmd/mecatui/ui/posture_badge_test.go b/cmd/mecatui/ui/posture_badge_test.go index 14a160eda1..29aadf2f13 100644 --- a/cmd/mecatui/ui/posture_badge_test.go +++ b/cmd/mecatui/ui/posture_badge_test.go @@ -108,7 +108,7 @@ func TestPostureSummary(t *testing.T) { {"yolo", []string{"posture yolo", "ceiling all modes including yolo", "child $()/heredoc auto-run when in yolo mode (injection-defense off) on", "project-trust on"}}, } for _, tc := range cases { - got := postureSummary(tc.posture, "") + got := postureSummary(tc.posture, "", "") for _, sub := range tc.want { if !strings.Contains(got, sub) { t.Errorf("postureSummary(%q) missing %q; got %q", tc.posture, sub, got) @@ -116,3 +116,38 @@ func TestPostureSummary(t *testing.T) { } } } + +// TestPostureShowsSubagentAskReviewer pins that /posture names the +// server-reported subagent ask reviewer state, says nothing about it when an +// older server omits it, and never echoes an unrecognized value raw. +func TestPostureShowsSubagentAskReviewer(t *testing.T) { + cases := []struct { + reviewer string + want string // "" means the reviewer must not be mentioned + }{ + {"", ""}, + {"on", "; subagent ask reviewer on (a model may approve subagent permission requests no human can answer)"}, + {"off", "; subagent ask reviewer off"}, + {"inert", "; subagent ask reviewer inert (configured, but you answer subagent permission requests)"}, + {"\x1b[31mfuture", "; subagent ask reviewer unknown"}, + } + for _, tc := range cases { + m, _, _ := newTestModel(t, theme.New("aztec", theme.AztecPalette())) + m = applyAll(m, tea.WindowSizeMsg{Width: 400, Height: 30}, + client.SessionReadyMsg{SessionID: "sess-test-0001", Capabilities: client.Capabilities{Posture: postureAuto, SubagentAskReviewer: tc.reviewer}}) + next, _ := m.runPosture() + got := stripANSIstr(next.(Model).statusMsg) + if tc.want == "" { + if strings.Contains(got, "subagent ask reviewer") { + t.Errorf("reviewer %q: /posture must not mention the reviewer; got %q", tc.reviewer, got) + } + continue + } + if !strings.Contains(got, tc.want) { + t.Errorf("reviewer %q: /posture missing %q; got %q", tc.reviewer, tc.want, got) + } + if strings.Contains(got, "future") { + t.Errorf("reviewer %q: unrecognized value echoed raw; got %q", tc.reviewer, got) + } + } +} diff --git a/cmd/mecatui/ui/testdata/help_all_on.golden b/cmd/mecatui/ui/testdata/help_all_on.golden index 7f676681ae..610300e438 100644 --- a/cmd/mecatui/ui/testdata/help_all_on.golden +++ b/cmd/mecatui/ui/testdata/help_all_on.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 89 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 90 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/testdata/help_embedded.golden b/cmd/mecatui/ui/testdata/help_embedded.golden index 1a237359e3..7f676681ae 100644 --- a/cmd/mecatui/ui/testdata/help_embedded.golden +++ b/cmd/mecatui/ui/testdata/help_embedded.golden @@ -16,7 +16,7 @@ ┃ also clears attachments, large pasted text, and pending media ┃ ┃ requires a terminal with enhanced key-event support ┃ ┃ fixed shortcut; repeats do not count, and other views handle esc first ┃ - ┃ lines 1–14 of 88 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ + ┃ lines 1–14 of 89 · esc or ? close · ↑/↓ scroll · pgup/pgdn page · home/end jump ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/update.go b/cmd/mecatui/ui/update.go index 68857b86eb..2bb74f47dc 100644 --- a/cmd/mecatui/ui/update.go +++ b/cmd/mecatui/ui/update.go @@ -1122,7 +1122,7 @@ func (m Model) updateLifecycle(msg tea.Msg) (tea.Model, tea.Cmd, bool) { if msg.Err == nil { checker = guardrailPostureSummary(msg.Coverage) } - m.statusMsg = m.deps.Theme.Style("muted").Render(postureSummary(m.caps.Posture, m.caps.ProjectTrust) + "; " + checker) + m.statusMsg = m.deps.Theme.Style("muted").Render(postureSummary(m.caps.Posture, m.caps.ProjectTrust, m.caps.SubagentAskReviewer) + "; " + checker) } else if msg.Err != nil { m.conv.addNotice("Guardrails status unavailable; checker state is unknown, not off or healthy.") } else { @@ -2303,12 +2303,6 @@ func (m Model) onKey(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { return mm, nil } - // A blocked permission mode holds the prompt before paste or any phase key - // can edit or send it. - if mm, handled := m.onModeBlockedKey(msg); handled { - return mm, nil - } - // ctrl+v reads the OS clipboard into the prompt (image → staged attachment, // text → inserted). It is handled here — before the phase switch — for the two // input-accepting phases (idle + running, both keep the textarea focused for @@ -2707,7 +2701,8 @@ func (m Model) onModeChanged(msg client.ModeChangedMsg) tea.Model { m.pendingMode = "" m.modeCursor = modeCursor{} m.modeRefused = requested - m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + requested + " refused: " + client.ModeErrorText(msg.Err)) + m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + requested + " refused, staying in " + m.acceptedModeToken() + + ": " + client.ModeErrorText(msg.Err) + modeRefusedHint(requested)) return m } m.pendingMode = requested @@ -2998,7 +2993,7 @@ func normalizePastedNewlines(content string) string { // primary-selection paste trigger (onMousePress), so the two paths can never // drift apart. func (m Model) pasteGateOpen() bool { - if m.phase == phaseAwaitingApproval || m.modeBlocked() || + if m.phase == phaseAwaitingApproval || m.modal != nil || m.team.view != teamNone || m.agentsInv.view != agentsInvNone { return false } @@ -5003,11 +4998,6 @@ func (m Model) popAndSubmit() (tea.Model, tea.Cmd) { m.pendingPromptMedia = m.queuedMedia m.queuedMedia = client.MediaResult{} m.prompt.Rewrite("/queue " + merged) - if m.modeBlocked() { - m.statusMsg = m.deps.Theme.Style("warning").Render("queued prompt held: " + m.modeBlockedStatus()) - m.queuePaused = "mode" - return m, nil - } if m.pendingMode != "" { submit := firstKey(m.keys.Submit, "enter") m.statusMsg = m.deps.Theme.Style("warning").Render("mode " + m.pendingMode + " will apply before the queued prompt — press " + submit + " to continue") diff --git a/cmd/mecatui/ui/view.go b/cmd/mecatui/ui/view.go index 539af1cdfb..289afa9cb7 100644 --- a/cmd/mecatui/ui/view.go +++ b/cmd/mecatui/ui/view.go @@ -224,22 +224,12 @@ func (m Model) headerModelLabel() string { return terminaltext.Sanitize(m.deps.Model) } -// modeBlockedSuffix marks a mode the cycle landed on that needs a restart, in the -// header's session mode and the input rail's mode key. -const modeBlockedSuffix = " blocked" - func (m Model) inputMode() string { - if m.modeBlocked() { - return m.currentModeToken() + modeBlockedSuffix - } return client.ModeString(client.ModeFromString(m.desiredMode())) } func modeAccentStyle(th theme.Theme, mode string) lipgloss.Style { s := lipgloss.NewStyle().Bold(true) - if strings.HasSuffix(mode, modeBlockedSuffix) { - return s.Foreground(th.Color("warning")) - } mode = client.ModeString(client.ModeFromString(strings.TrimSuffix(mode, " pending"))) switch mode { case "plan": @@ -621,9 +611,6 @@ func (m Model) renderPendingPrompt(status string, texts []string, hints string) // chrome()), so the cache is re-keyed in the same step the mutation lands — there // is no window in which a hidden-state change can hide behind an unchanged key. func (m Model) renderInput() string { - if m.modeBlocked() { - return m.renderModeBlocked() - } m.applyModeInputStyle() li := m.prompt.LineInfo() hasSelection := m.prompt.HasSelection() diff --git a/contracts/gen/go/mecatl/v1/harness.pb.go b/contracts/gen/go/mecatl/v1/harness.pb.go index 665af9b3b7..94108128c4 100644 --- a/contracts/gen/go/mecatl/v1/harness.pb.go +++ b/contracts/gen/go/mecatl/v1/harness.pb.go @@ -1987,8 +1987,15 @@ type ServerCapabilities struct { // the permission mode. CHROME ONLY. Additive: an older server leaves it // unset and the client shows no trust indicator. ProjectTrusted *bool `protobuf:"varint,32,opt,name=project_trusted,json=projectTrusted,proto3,oneof" json:"project_trusted,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // subagent_ask_reviewer reports the subagent ask reviewer, a model that may + // approve a subagent's, team member's, or parallel branch's permission + // request that no human can answer: "on" (enabled), "off" (not enabled), or + // "inert" (configured, but an interactive approver answers instead). Clients + // treat other values as unknown. CHROME ONLY. Additive: an older server + // leaves it unset and the client shows nothing. + SubagentAskReviewer *string `protobuf:"bytes,33,opt,name=subagent_ask_reviewer,json=subagentAskReviewer,proto3,oneof" json:"subagent_ask_reviewer,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServerCapabilities) Reset() { @@ -2231,6 +2238,13 @@ func (x *ServerCapabilities) GetProjectTrusted() bool { return false } +func (x *ServerCapabilities) GetSubagentAskReviewer() string { + if x != nil && x.SubagentAskReviewer != nil { + return *x.SubagentAskReviewer + } + return "" +} + // ListSessionMcpConnectorsRequest names an owned, broker-bound session. type ListSessionMcpConnectorsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -19805,7 +19819,7 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 0x73, 0x12, 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, 0xdc, 0x08, + 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xaf, 0x09, 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, @@ -19871,3207 +19885,3212 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x72, - 0x75, 0x73, 0x74, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x14, - 0x10, 0x15, 0x4a, 0x04, 0x08, 0x15, 0x10, 0x16, 0x52, 0x0f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x5f, 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x73, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x67, 0x72, 0x61, 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, 0xdf, 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, 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, 0x12, 0x43, 0x0a, 0x1e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x64, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x72, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 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, 0x90, 0x01, 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, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x24, - 0x0a, 0x0e, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x68, 0x65, 0x6c, 0x6c, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x49, 0x6e, 0x53, - 0x68, 0x65, 0x6c, 0x6c, 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, 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, 0xb5, 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, 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, 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, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, - 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x09, 0x77, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, - 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x37, 0x0a, 0x15, 0x73, 0x75, 0x62, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, + 0x72, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x13, 0x73, 0x75, 0x62, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x88, 0x01, + 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x73, 0x75, 0x62, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x5f, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x4a, + 0x04, 0x08, 0x14, 0x10, 0x15, 0x4a, 0x04, 0x08, 0x15, 0x10, 0x16, 0x52, 0x0f, 0x6c, 0x65, 0x67, + 0x61, 0x63, 0x79, 0x5f, 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x67, 0x72, 0x61, 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, + 0xdf, 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, 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, 0x12, 0x43, 0x0a, 0x1e, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x1b, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, + 0x02, 0x10, 0x03, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, + 0x73, 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, 0x90, 0x01, 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, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, + 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x68, + 0x65, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x74, + 0x49, 0x6e, 0x53, 0x68, 0x65, 0x6c, 0x6c, 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, 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, 0xb5, 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, + 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, 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, 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, + 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, 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, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x0d, + 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, + 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, + 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, 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, 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, - 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, 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, + 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, 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, 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, - 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, + 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, 0x53, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, - 0x61, 0x6e, 0x63, 0x79, 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, 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, - 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, - 0x6d, 0x61, 0x74, 0x65, 0x64, 0x22, 0x8f, 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, 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, + 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, 0x53, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, + 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 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, 0x1c, 0x0a, 0x09, 0x65, 0x73, + 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, + 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x22, 0x8f, 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, 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, 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, 0x12, 0x55, - 0x0a, 0x18, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x5f, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x16, 0x6c, - 0x61, 0x74, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, - 0x70, 0x61, 0x6e, 0x63, 0x79, 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, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, - 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0c, 0x63, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, + 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, 0x12, 0x55, 0x0a, 0x18, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x5f, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x16, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, + 0x52, 0x16, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4f, + 0x63, 0x63, 0x75, 0x70, 0x61, 0x6e, 0x63, 0x79, 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, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, + 0x4a, 0x04, 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0c, + 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x10, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 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, 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, 0xb3, 0x01, 0x0a, 0x06, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x26, + 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, 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, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, - 0x77, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, - 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8f, 0x02, 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, 0x42, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, - 0x06, 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, 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, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, - 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, - 0x69, 0x6c, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, - 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x04, - 0x08, 0x02, 0x10, 0x03, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 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, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xb3, 0x01, 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, 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, 0xb9, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, - 0x63, 0x74, 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, 0x18, 0x01, 0x18, 0x02, - 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, + 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x1b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x6e, + 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8f, 0x02, 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, + 0x42, 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, 0x42, 0x0c, 0xba, 0x48, + 0x09, 0x82, 0x01, 0x06, 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, 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, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4b, 0x69, 0x6e, - 0x64, 0x22, 0x45, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, - 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, - 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, - 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, - 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, - 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, - 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x22, - 0x46, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, - 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x6b, 0x0a, 0x10, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x52, 0x75, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, - 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, - 0x75, 0x6e, 0x49, 0x64, 0x22, 0x2a, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, - 0x22, 0xc2, 0x02, 0x0a, 0x0f, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 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, 0x2f, 0x0a, 0x0f, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x42, 0x08, 0xba, 0x48, 0x05, 0x92, 0x01, 0x02, 0x10, 0x10, 0x52, 0x05, - 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x18, 0x40, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x3a, 0x66, 0xba, - 0x48, 0x63, 0x1a, 0x61, 0x0a, 0x11, 0x73, 0x74, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x75, 0x6e, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x74, 0x65, 0x78, 0x74, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, - 0x6f, 0x74, 0x68, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x27, 0x74, 0x68, - 0x69, 0x73, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x27, 0x20, 0x7c, 0x7c, - 0x20, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x61, 0x72, 0x74, 0x73, - 0x29, 0x20, 0x3e, 0x20, 0x30, 0x22, 0x7b, 0x0a, 0x10, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, 0x0a, 0x06, - 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, - 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, - 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x18, 0x40, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x81, 0x01, - 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, 0x0a, 0x06, 0x72, - 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 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, 0x50, 0x0a, 0x17, 0x50, - 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x72, - 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6c, 0x61, - 0x6e, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xb4, 0x09, - 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, 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, + 0x64, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 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, 0xb9, 0x02, 0x0a, 0x14, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x06, 0x61, 0x73, + 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x04, 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, - 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, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x72, - 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x6e, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, - 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x17, - 0x70, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x52, 0x05, 0x75, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x43, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, - 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1a, 0x0a, - 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 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, - 0x3c, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x12, - 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, - 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0xb9, 0x04, - 0x0a, 0x0f, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x29, - 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x73, 0x73, - 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, - 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, - 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x64, 0x69, 0x73, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, - 0x72, 0x61, 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, - 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x75, 0x6c, - 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, - 0x64, 0x12, 0x33, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x52, 0x08, 0x63, 0x6f, - 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, - 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xe2, 0x01, 0x0a, 0x16, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, - 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, - 0x64, 0x12, 0x34, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, - 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, - 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, - 0x72, 0x61, 0x6e, 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x29, 0x0a, - 0x10, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x41, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x3d, - 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, - 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, + 0x56, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x82, 0x01, 0x06, 0x18, + 0x01, 0x18, 0x02, 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, + 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, + 0x4b, 0x69, 0x6e, 0x64, 0x22, 0x45, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, + 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, + 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, + 0x75, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a, 0x15, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 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, 0x2f, 0x0a, + 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1e, + 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x42, + 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x04, 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, 0x42, 0x0c, 0xba, 0x48, 0x09, + 0x82, 0x01, 0x06, 0x18, 0x01, 0x18, 0x02, 0x18, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, + 0x63, 0x74, 0x22, 0x46, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, + 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, + 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, + 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x6b, 0x0a, 0x10, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 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, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x93, 0x02, - 0x0a, 0x16, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, - 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, - 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, - 0x73, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x12, 0x0a, - 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, - 0x6c, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x72, 0x75, 0x6c, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x3e, 0x0a, 0x0a, 0x69, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0a, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x22, 0xd0, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, - 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x65, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, - 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, - 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, - 0x69, 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, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, - 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, - 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, - 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, - 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, - 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, - 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, - 0x65, 0x78, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb6, 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, 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, 0x34, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x06, 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, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, - 0x08, 0x05, 0x10, 0x06, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 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, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x2a, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, + 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, + 0x6e, 0x49, 0x64, 0x22, 0xc2, 0x02, 0x0a, 0x0f, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 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, + 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x65, 0x78, 0x74, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x04, 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, - 0xb8, 0x01, 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, - 0x12, 0x38, 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, - 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x22, 0xb8, 0x03, 0x0a, 0x0f, 0x52, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x6f, - 0x64, 0x65, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x61, 0x6e, - 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0a, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, - 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, - 0x12, 0x32, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x11, - 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x2d, - 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x69, - 0x73, 0x73, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1d, 0x0a, - 0x0a, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x09, 0x6d, 0x69, 0x73, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x21, 0x0a, 0x0c, - 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x6e, 0x42, - 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x15, - 0x0a, 0x13, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x64, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x81, 0x06, 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, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x08, 0xba, 0x48, 0x05, 0x92, 0x01, 0x02, 0x10, + 0x10, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x18, 0x40, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, + 0x3a, 0x66, 0xba, 0x48, 0x63, 0x1a, 0x61, 0x0a, 0x11, 0x73, 0x74, 0x65, 0x65, 0x72, 0x5f, 0x72, + 0x75, 0x6e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x27, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x27, + 0x20, 0x7c, 0x7c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x61, + 0x72, 0x74, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x22, 0x7b, 0x0a, 0x10, 0x53, 0x74, 0x65, 0x65, + 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, + 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x2f, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x18, 0x40, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, + 0x22, 0x81, 0x01, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, + 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x15, + 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 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, 0x50, + 0x0a, 0x17, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x6c, 0x61, + 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x70, 0x6c, 0x61, 0x6e, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, + 0x22, 0xb4, 0x09, 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, 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, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x5f, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x19, 0x70, 0x6c, + 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, + 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, + 0x65, 0x52, 0x17, 0x70, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, + 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x22, 0x43, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x52, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 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, 0x3c, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, + 0x65, 0x66, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x72, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, + 0x22, 0xb9, 0x04, 0x0a, 0x0f, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, + 0x64, 0x12, 0x29, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, + 0x72, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x12, 0x3e, 0x0a, 0x0a, + 0x61, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0a, + 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, + 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, + 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6c, + 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x72, 0x75, 0x6c, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x4d, 0x6f, 0x64, + 0x65, 0x6c, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, + 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x66, 0x52, + 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, + 0x52, 0x65, 0x66, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xe2, 0x01, 0x0a, + 0x16, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, + 0x61, 0x6c, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, + 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, + 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, + 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x65, + 0x61, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x04, 0x08, 0x06, 0x10, + 0x07, 0x22, 0x3d, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, + 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 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, 0x93, 0x02, 0x0a, 0x16, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, + 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, + 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, + 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x72, 0x75, 0x6c, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x3e, + 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xd0, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x07, + 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, + 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x1f, 0x47, 0x65, 0x74, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, + 0x65, 0x74, 0x61, 0x69, 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, 0x1b, 0x0a, 0x09, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, + 0x09, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, + 0x63, 0x65, 0x72, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, + 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb6, 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, 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, 0x34, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x06, 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, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x02, 0x10, + 0x03, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, + 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, 0xb8, 0x01, 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, 0x12, 0x38, 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x52, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x22, 0xb8, 0x03, + 0x0a, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, + 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x11, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x74, + 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x23, + 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x01, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, + 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x48, + 0x01, 0x52, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x64, + 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, + 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, + 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x73, + 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6d, 0x69, 0x73, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, + 0x21, 0x0a, 0x0c, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x4f, 0x70, + 0x65, 0x6e, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, + 0x65, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x81, 0x06, 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, + 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, + 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, + 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, + 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, + 0x18, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x16, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, + 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, + 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x03, 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, + 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, + 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, + 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x74, 0x65, + 0x67, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, + 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, + 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, + 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc5, 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, 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, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, + 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x63, 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x22, + 0xb5, 0x07, 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, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, + 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, 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, - 0x01, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, - 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, - 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, - 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, - 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, - 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x03, 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, 0x12, 0x4a, 0x0a, - 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, - 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, - 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, - 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, - 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc5, 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, 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, 0x12, - 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, - 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x22, 0xb5, 0x07, 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, - 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, - 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, - 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, - 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, - 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, - 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, - 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 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, + 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, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x6f, + 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1a, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x48, 0x00, 0x52, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, + 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x1b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, + 0x6c, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, + 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, + 0x38, 0x0a, 0x18, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x1d, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x16, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x6f, + 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 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, 0xd1, 0x01, 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, 0x12, 0x3f, 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, + 0x61, 0x6c, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x52, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, + 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x88, 0x01, 0x01, + 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0xc1, 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, 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, 0x4a, + 0x04, 0x08, 0x05, 0x10, 0x06, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, + 0x22, 0x70, 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, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, + 0x65, 0x64, 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, + 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, 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, 0xd1, 0x01, 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, 0x12, 0x3f, - 0x0a, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, - 0x63, 0x6f, 0x70, 0x65, 0x52, 0x09, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x12, - 0x1c, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, - 0x08, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0xc1, 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, 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, 0x4a, 0x04, 0x08, 0x05, - 0x10, 0x06, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x22, 0x70, 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, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 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, + 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, 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, 0x5b, 0x0a, 0x0d, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, - 0x69, 0x6c, 0x65, 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, 0x12, 0x0a, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, - 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x34, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x22, 0x48, 0x0a, 0x16, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x1b, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x15, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 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, + 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, 0x5b, 0x0a, 0x0d, 0x53, 0x6b, 0x69, + 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 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, 0x12, + 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, + 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x34, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, + 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x22, 0x48, 0x0a, 0x16, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, + 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x1b, 0x0a, 0x04, 0x66, + 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x15, 0x52, 0x65, 0x61, 0x64, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 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, 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, 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, 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, 0xdd, 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, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x5f, 0x63, 0x61, 0x63, - 0x68, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, - 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 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, + 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, 0xdd, 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, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x5f, + 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, 0x72, + 0x6f, 0x6d, 0x70, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 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, 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, + 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, 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, + 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, - 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, + 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, 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, 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, 0xbe, - 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, 0x12, 0x18, 0x0a, 0x14, 0x50, - 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, - 0x55, 0x54, 0x4f, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x59, 0x4f, 0x4c, 0x4f, 0x10, 0x05, 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, 0x80, 0x01, 0x0a, 0x0c, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, - 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, - 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, - 0x19, 0x0a, 0x15, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, - 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x47, 0x55, - 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x50, 0x45, 0x52, 0x4d, - 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xaa, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, - 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, - 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, - 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, - 0x43, 0x43, 0x45, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x47, - 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, - 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, - 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, - 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x53, 0x4f, 0x4c, - 0x56, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, - 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, - 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x50, - 0x4c, 0x45, 0x54, 0x45, 0x10, 0x01, 0x12, 0x2c, 0x0a, 0x28, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, - 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, - 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, - 0x52, 0x45, 0x10, 0x02, 0x2a, 0xd0, 0x02, 0x0a, 0x14, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, - 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, - 0x21, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 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, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, - 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x58, - 0x45, 0x43, 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, + 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, 0xbe, 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, 0x12, 0x18, + 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, + 0x45, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, + 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x59, 0x4f, 0x4c, 0x4f, + 0x10, 0x05, 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, 0x80, 0x01, 0x0a, 0x0c, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x55, 0x41, + 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x47, 0x55, 0x41, 0x52, + 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, + 0x4a, 0x4f, 0x42, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, + 0x18, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x50, + 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xaa, 0x01, 0x0a, 0x13, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, + 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, + 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, + 0x54, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x23, + 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x53, 0x53, 0x45, + 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x48, 0x49, 0x42, 0x49, 0x54, 0x45, + 0x44, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, + 0x5f, 0x41, 0x53, 0x53, 0x45, 0x53, 0x53, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x52, 0x45, + 0x53, 0x4f, 0x4c, 0x56, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x8c, 0x01, 0x0a, 0x13, 0x47, 0x75, 0x61, + 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, + 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, + 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x01, 0x12, 0x2c, 0x0a, 0x28, 0x47, 0x55, 0x41, + 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x02, 0x2a, 0xd0, 0x02, 0x0a, 0x14, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x25, 0x0a, 0x21, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 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, 0x21, 0x0a, 0x1d, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x41, 0x53, 0x4b, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x29, 0x0a, - 0x25, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, - 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x48, 0x4f, 0x4c, 0x44, 0x5f, - 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x47, 0x55, 0x41, 0x52, - 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, - 0x10, 0x04, 0x12, 0x1e, 0x0a, 0x1a, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, - 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, - 0x10, 0x05, 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, - 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x53, 0x53, - 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, 0x2a, 0x0a, 0x26, 0x47, + 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x55, + 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x53, 0x4b, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, + 0x12, 0x29, 0x0a, 0x25, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, + 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x48, 0x4f, + 0x4c, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x45, 0x5f, 0x57, 0x41, - 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x2a, 0x90, 0x01, 0x0a, 0x15, 0x47, 0x75, 0x61, 0x72, - 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x4b, 0x69, 0x6e, - 0x64, 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, - 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x47, 0x55, - 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, - 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x2a, - 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, - 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, - 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x02, 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, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x53, + 0x55, 0x4c, 0x54, 0x10, 0x04, 0x12, 0x1e, 0x0a, 0x1a, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, + 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, + 0x45, 0x4e, 0x59, 0x10, 0x05, 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, + 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, + 0x41, 0x53, 0x53, 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, 0x2a, + 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x50, + 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x55, 0x45, + 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x2a, 0x90, 0x01, 0x0a, 0x15, 0x47, + 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, + 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x23, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, + 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, + 0x1e, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, + 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, + 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x47, 0x55, 0x41, 0x52, 0x44, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x41, + 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, + 0x55, 0x4c, 0x54, 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x02, 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, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x10, 0x03, - 0x32, 0x9c, 0x39, 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, 0x6d, 0x0a, 0x16, + 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, 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, 0x9c, 0x39, 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, + 0x6d, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x73, 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, 0x6a, - 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, - 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, - 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, 0x47, 0x65, - 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 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, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, - 0x41, 0x73, 0x6b, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 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, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, - 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, - 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, - 0x09, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x63, + 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, 0x6a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, + 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, + 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x76, + 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, + 0x18, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, + 0x69, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x52, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 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, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x75, 0x6e, 0x41, 0x73, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x20, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x50, + 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x46, 0x0a, 0x09, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x12, 0x1b, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, - 0x6e, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, - 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, - 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, - 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 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, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x53, 0x74, 0x65, 0x65, + 0x72, 0x52, 0x75, 0x6e, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, + 0x65, 0x72, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, + 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, + 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 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, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 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, - 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, + 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, 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, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, + 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, 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, 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, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, + 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, 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, 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, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, - 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x12, - 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, - 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, - 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 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, + 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, + 0x6c, 0x6c, 0x46, 0x69, 0x6c, 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, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, + 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x61, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x65, 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 0x12, 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, + 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 ( diff --git a/contracts/proto/mecatl/v1/harness.proto b/contracts/proto/mecatl/v1/harness.proto index d8fe043e37..8f654cfe53 100644 --- a/contracts/proto/mecatl/v1/harness.proto +++ b/contracts/proto/mecatl/v1/harness.proto @@ -881,6 +881,13 @@ message ServerCapabilities { // the permission mode. CHROME ONLY. Additive: an older server leaves it // unset and the client shows no trust indicator. optional bool project_trusted = 32; + // subagent_ask_reviewer reports the subagent ask reviewer, a model that may + // approve a subagent's, team member's, or parallel branch's permission + // request that no human can answer: "on" (enabled), "off" (not enabled), or + // "inert" (configured, but an interactive approver answers instead). Clients + // treat other values as unknown. CHROME ONLY. Additive: an older server + // leaves it unset and the client shows nothing. + optional string subagent_ask_reviewer = 33; } // ListSessionMcpConnectorsRequest names an owned, broker-bound session. diff --git a/deploy/helm/mecak8s/chart_test.go b/deploy/helm/mecak8s/chart_test.go index 7f3ef4651e..a7b53dd611 100644 --- a/deploy/helm/mecak8s/chart_test.go +++ b/deploy/helm/mecak8s/chart_test.go @@ -924,7 +924,6 @@ func TestMecak8sHelmChart_DeployCheckProductionFixtureRuntimeAndSpread(t *testin "--session-lease-k8s-namespace=default", "--headless=true", "--permission-mode=auto", - "--guardrails=off", "--default-provider=openrouter", "--model=anthropic/claude-sonnet-4-6", "--max-run-tokens=200000", @@ -3074,20 +3073,23 @@ mcp: } } -// TestShippedAllowAllDefaultsDeclareCheckerChoice pins the checker declaration for -// the chart: it runs mecak8s in the allow-all auto permission mode, and mecak8s -// refuses that mode without a checker, so every render must declare the checker -// choice. An empty guardrails.model is the explicit unsupervised --guardrails=off; -// a set model becomes --guardrails-model and never carries the kill-switch. +// TestShippedAllowAllDefaultsDeclareCheckerChoice pins the chart's tri-state +// checker choice: with neither guardrails.model nor guardrails.disabled set the +// chart passes no guardrails flag, so mecak8s inherits the checker from mounted +// settings; a model renders --guardrails-model; disabled renders the +// --guardrails=off kill-switch. permissionMode renders --permission-mode. func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { cases := []struct { - name string - extra []string - want string - notWant string + name string + extra []string + mode string + guardArg string // the single expected --guardrails* arg; empty means none }{ - {name: "default declares unsupervised", want: "--guardrails=off", notWant: "--guardrails-model="}, - {name: "model declares checker", extra: []string{"--set-string", "guardrails.model=openrouter/checker"}, want: "--guardrails-model=openrouter/checker", notWant: "--guardrails=off"}, + {name: "default inherits the settings checker", mode: "auto"}, + {name: "model declares checker", extra: []string{"--set-string", "guardrails.model=openrouter/checker"}, mode: "auto", guardArg: "--guardrails-model=openrouter/checker"}, + {name: "disabled declares the kill-switch", extra: []string{"--set", "permissionMode=yolo,guardrails.disabled=true"}, mode: "yolo", guardArg: "--guardrails=off"}, + {name: "yolo inherits", extra: []string{"--set", "permissionMode=yolo"}, mode: "yolo"}, + {name: "default mode", extra: []string{"--set", "permissionMode=default"}, mode: "default"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -3096,20 +3098,54 @@ func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { t.Fatalf("render: %v\n%s", err, rendered) } args := deploymentFromRender(t, rendered).Spec.Template.Spec.Containers[0].Args - if !slices.Contains(args, "--permission-mode=auto") { - t.Fatalf("args lack --permission-mode=auto: %q", args) + if !slices.Contains(args, "--permission-mode="+tc.mode) { + t.Fatalf("args lack --permission-mode=%s: %q", tc.mode, args) } + var guard []string for _, a := range args { if strings.HasPrefix(a, "--posture") || a == "--yolo" { t.Fatalf("args still use deprecated alias %q: %q", a, args) } + if strings.HasPrefix(a, "--guardrails") { + guard = append(guard, a) + } } - if !slices.Contains(args, tc.want) { - t.Fatalf("args lack checker choice %q: %q", tc.want, args) + var want []string + if tc.guardArg != "" { + want = []string{tc.guardArg} } - for _, a := range args { - if strings.HasPrefix(a, tc.notWant) { - t.Fatalf("args carry conflicting %q: %q", a, args) + if !slices.Equal(guard, want) { + t.Fatalf("guardrails args = %q, want %q", guard, want) + } + }) + } +} + +// TestPermissionModeValuesAreValidated pins the chart-owned permission mode: +// an unknown permissionMode, a mode flag in extraArgs, or both checker choices +// fail rendering with a message naming the fix. +func TestPermissionModeValuesAreValidated(t *testing.T) { + cases := []struct { + name string + extra []string + want []string + }{ + {name: "unknown mode", extra: []string{"--set", "permissionMode=trusted"}, want: []string{"permissionMode", "plan, default, accept-edits, auto, yolo"}}, + {name: "posture in extraArgs", extra: []string{"--set", "extraArgs[0]=--posture=strict"}, want: []string{"--posture=strict", "permissionMode"}}, + {name: "split posture in extraArgs", extra: []string{"--set", "extraArgs[0]=--posture,extraArgs[1]=auto"}, want: []string{"--posture", "permissionMode"}}, + {name: "permission-mode in extraArgs", extra: []string{"--set", "extraArgs[0]=--permission-mode=yolo"}, want: []string{"--permission-mode=yolo", "permissionMode"}}, + {name: "yolo in extraArgs", extra: []string{"--set", "extraArgs[0]=--yolo"}, want: []string{"--yolo", "permissionMode"}}, + {name: "model and disabled", extra: []string{"--set", "guardrails.model=checker,guardrails.disabled=true"}, want: []string{"guardrails.model", "guardrails.disabled"}}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + rendered, err := helm(t, append(secureProductionArgs(), tc.extra...)...) + if err == nil { + t.Fatalf("render succeeded, want failure:\n%s", rendered) + } + for _, w := range tc.want { + if !strings.Contains(rendered, w) { + t.Fatalf("render error lacks %q:\n%s", w, rendered) } } }) diff --git a/deploy/helm/mecak8s/templates/_helpers.tpl b/deploy/helm/mecak8s/templates/_helpers.tpl index f6a1a08649..a4294905b1 100644 --- a/deploy/helm/mecak8s/templates/_helpers.tpl +++ b/deploy/helm/mecak8s/templates/_helpers.tpl @@ -155,6 +155,23 @@ mounted {{- end -}} {{- end -}} +{{/* Validate the permission mode and guardrails checker choice. */}} +{{- define "mecak8s.validatePermissionMode" -}} +{{- $modes := list "plan" "default" "accept-edits" "auto" "yolo" -}} +{{- if not (has .Values.permissionMode $modes) -}} +{{- fail (printf "permissionMode %q is invalid: valid values are %s" (toString .Values.permissionMode) (join ", " $modes)) -}} +{{- end -}} +{{- range $arg := .Values.extraArgs -}} +{{- $a := toString $arg -}} +{{- if or (hasPrefix "--posture" $a) (hasPrefix "--permission-mode" $a) (hasPrefix "--yolo" $a) -}} +{{- fail (printf "extraArgs entry %q sets the permission mode, which the chart owns; remove it and set permissionMode instead (--posture=strict becomes permissionMode: default, --posture=auto becomes permissionMode: auto, --posture=yolo or --yolo becomes permissionMode: yolo)" $a) -}} +{{- end -}} +{{- end -}} +{{- if and .Values.guardrails.model .Values.guardrails.disabled -}} +{{- fail "set at most one of guardrails.model or guardrails.disabled" -}} +{{- end -}} +{{- end -}} + {{/* Validate cross-entry MCP invariants that JSON Schema cannot express. */}} {{- define "mecak8s.validateMCP" -}} {{- $seen := dict -}} diff --git a/deploy/helm/mecak8s/templates/deployment.yaml b/deploy/helm/mecak8s/templates/deployment.yaml index 1ce2dbac85..efd97cf386 100644 --- a/deploy/helm/mecak8s/templates/deployment.yaml +++ b/deploy/helm/mecak8s/templates/deployment.yaml @@ -4,6 +4,7 @@ {{- include "mecak8s.validateTLS" . -}} {{- include "mecak8s.validateLearningStore" . -}} {{- include "mecak8s.validateProviderSecurity" . -}} +{{- include "mecak8s.validatePermissionMode" . -}} {{- $learningStoreEnabled := ne .Values.learning.store.endpoint "" -}} {{- $learningStoreTokenConfigured := and .Values.learning.store.tokenSecret .Values.learning.store.tokenKey -}} {{- include "mecak8s.validateMCP" . -}} @@ -111,10 +112,10 @@ spec: {{- end }} - {{ printf "--session-lease-k8s-namespace=%s" .Release.Namespace | quote }} - --headless=true - - --permission-mode=auto + - {{ printf "--permission-mode=%s" .Values.permissionMode | quote }} {{- if .Values.guardrails.model }} - {{ printf "--guardrails-model=%s" .Values.guardrails.model | quote }} - {{- else }} + {{- else if .Values.guardrails.disabled }} - --guardrails=off {{- end }} {{- if .Values.logging.level }} diff --git a/deploy/helm/mecak8s/values.schema.json b/deploy/helm/mecak8s/values.schema.json index f4fa71530e..7dd1028ab0 100644 --- a/deploy/helm/mecak8s/values.schema.json +++ b/deploy/helm/mecak8s/values.schema.json @@ -103,9 +103,11 @@ {"const": ""}, {"pattern": "^\\S(?:.*\\S)?$"} ] - } + }, + "disabled": {"type": "boolean"} } }, + "permissionMode": {"type": "string"}, "telemetry": { "type": "object", "additionalProperties": false, diff --git a/deploy/helm/mecak8s/values.yaml b/deploy/helm/mecak8s/values.yaml index eb786e54e3..0dfddf034b 100644 --- a/deploy/helm/mecak8s/values.yaml +++ b/deploy/helm/mecak8s/values.yaml @@ -36,7 +36,9 @@ logging: # extraArgs appends command-line arguments to the mecak8s agent container. It remains # the escape hatch for flags not modeled by the chart; when it contains --log-level, -# it is appended after logging.level and therefore takes precedence. +# it is appended after logging.level and therefore takes precedence. The chart owns +# the permission mode: rendering fails if extraArgs sets --posture, +# --permission-mode, or --yolo; set permissionMode instead. extraArgs: [] # First-class remote Streamable HTTP MCP connections. Authentication is an @@ -110,19 +112,28 @@ model: "" maxRunTokens: null maxTeamTokens: null -# guardrails declares the checker choice for the chart's allow-all permission -# mode (--permission-mode=auto: every tool runs without asking, only deny rules -# and configured ask rules still apply). mecak8s refuses to start an allow-all -# mode without a checker unless the operator opts out explicitly, so the chart -# always passes one of two flags: -# - model set: --guardrails-model=, a tool-free checker model that -# inspects outbound tool arguments and inbound results. -# - model empty (the default): --guardrails=off, a DELIBERATE choice to run -# unsupervised, with no checker inspecting tool content. The kill-switch also -# disables a guardrail model slot bound in mounted settings, so set model here -# to the checker you want rather than relying on a slot. +# permissionMode renders --permission-mode=: one of plan, default, +# accept-edits, auto, or yolo. auto (the default) runs every tool without asking; +# only deny rules and configured ask rules still apply. mecak8s refuses to start +# in auto without an ENFORCING guardrails checker: set guardrails.model, or bind +# a checker in mounted settings (a `guardrails:` model or the `guardrail` model +# slot). yolo is the explicit choice to run every tool without a checker. +# Migration: earlier charts always ran --posture=auto with --guardrails=off. Such +# a deployment must now configure a checker or set permissionMode: yolo. Move +# any --posture, --permission-mode, or --yolo entry from extraArgs to this +# value (--posture=strict is permissionMode: default). +permissionMode: auto + +# guardrails selects the checker for tool arguments and results. Set at most one: +# - neither (the default): the chart passes no guardrails flag, so mecak8s uses +# the checker configured in mounted settings, if any. +# - model: --guardrails-model=, a tool-free checker model that inspects +# outbound tool arguments and inbound results. +# - disabled: true: --guardrails=off, the kill-switch. It also disables a +# checker configured in mounted settings, and auto refuses to start with it. guardrails: model: "" + disabled: false # Stable, non-secret identity exported on mecak8s OTel resources. Empty is safe # only for live Helm install/upgrade: Helm creates a UUID on install and preserves diff --git a/docs/architecture/governance.md b/docs/architecture/governance.md index e789f67239..db72ef6951 100644 --- a/docs/architecture/governance.md +++ b/docs/architecture/governance.md @@ -51,29 +51,56 @@ One Shell line can hold many programs, so `engine/governance/shell.go` decompose Plan mode uses the separate `ReadOnlyShell` classifier. Children add approval steps for floored segments; see [subagents and teams](subagents-and-teams.md). -## Posture ladder - -Posture (`internal/app/posture.go`) is the one operator knob for how much the harness -approves on its own. It composes rules and evaluator options; it never bypasses the -evaluator. - -| Posture | Allow-all rule | Substitution floor loosened | Raises project trust | -| --- | --- | --- | --- | -| `strict` (default) | No | No | No | -| `trusted` | No | No | Unless headless | -| `auto` | Main and children | Main engine | Unless headless | -| `yolo` | Main and children | Main and children | Unless headless | - -`trusted` changes no permission rule; its only effect is raising project trust. Headless -is a per-binary setting, not inferred from the environment: `mecatui` is always -interactive, `mecated` is interactive unless started with `--headless`, and `mecak8s` and -`mecatequi` default to headless. +## Permission modes + +The operator's `--permission-mode` token or `permissionMode:` key +(`internal/app/permission_mode.go`) sets two values: the mode new sessions start in and +the server ceiling (`MaxAllowedMode`), the most permissive mode a session may enter. +`plan`, `default`, and `accept-edits` share the ceiling `accept-edits`; `auto` and `yolo` +are their own ceilings. Allow-all is driven by each session's current mode at +evaluation time, not by a process-wide posture, so switching a session from `yolo` to +`default` restores ordinary asks. Modes compose rules and evaluator options; they never +bypass the evaluator. + +| Session mode | Allow-all rule | Substitution floor loosened | +| --- | --- | --- | +| `plan`, `default`, `accept-edits` | No | No | +| `auto` | Main and children | Main engine | +| `yolo` | Main and children | Main and children | The allow-all rule is one ordinary `ScopeCLI` Allow, pinned per audience, so it loosens only the built-in floor: every Deny and configured Ask still applies at `yolo`. Only `yolo` lets children auto-run substitutions, which turns off the child prompt-injection -defense. A project file's `posture:` is ignored with a warning, an unknown value fails -closed to `strict`, and `auto` or `yolo` are refused as root without a declared sandbox. +defense. + +`Service.admitMode` (`internal/adapter/server/service.go`) refuses a created or switched +mode above the ceiling, and `auto` without an enforcing guardrails checker; a server +whose default mode is `auto` refuses to start without one. Unchecked autonomy is the +explicit `yolo` choice, where a configured checker is advisory. `admitStoredMode` +re-checks a persisted session's mode at run, approval resume, fork, and clear, so a +mode admitted under a looser deployment fails with `FailedPrecondition` until the owner +switches it; history is untouched. A project file's `permissionMode:` is ignored with a +warning, and `auto` or `yolo` are refused as root without a declared sandbox. + +Delegated children receive the parent session's mode through `parentCaps.parentMode`: +`effectiveChildMode` (`engine/agent/subagent.go`) runs a default-configured Subagent +child, Parallel branch, or Team member in its parent's mode when that mode is `auto` or +`yolo`, and keeps an explicitly configured child mode or a member definition's +`permissionMode`. `Service.AdmittedModes` lists the modes `admitMode` accepts, which the +ACP adapter offers as its mode picker. + +A mode change is a session-aggregate transition that `session.SetMode` refuses while the +session is `StateAwaiting`: a pending ask is resolved under the mode it was raised in, +and the new mode applies from the next run. Re-evaluating a parked ask on a mode switch +is deliberately not supported; a mode change never interrupts a command that has +already started. + +A mode never grants project trust. The deprecated `--posture` ladder +(`strict < trusted < auto < yolo`, `internal/app/posture.go`) still raises project +trust on an interactive root; combining it with `--permission-mode` is an error. +Headless is a per-binary setting, not inferred from the environment: `mecatui` is always +interactive, `mecated` is interactive unless started with `--headless`, and `mecak8s` and +`mecatequi` default to headless. ## Workspace trust diff --git a/engine/CHANGELOG.md b/engine/CHANGELOG.md index e327f00257..d2c7c6e8ab 100644 --- a/engine/CHANGELOG.md +++ b/engine/CHANGELOG.md @@ -449,6 +449,14 @@ The covered surface is the eight core packages (`session`, `governance`, `learni before persisting them. Changed (breaking pre-v1 minor); existing ordinary-session wire clients are unaffected. +- **Delegated children inherit an auto or yolo parent's mode** — a Subagent + child, Parallel branch, or Team member whose configured mode is the default + (`ModeDefault`) now runs in its parent session's mode when that mode is + `ModeAuto` or `ModeYolo`, so the parent's mode-driven authority reaches its + delegates. An explicitly configured narrower mode (`WithChildMode`, + `WithParallelChildMode`, `WithTeamMode`, or a member definition's + `permissionMode`) is kept. No signature changes. + - **Atomic one-shot retry eligibility (issue #2273)** — `port.ScheduleOneShotReArmer.ReArmOneShot` now requires store-side atomic validation of current disabled/settled-failure state, one-shot retry policy, diff --git a/engine/agent/child_mode_inherit_test.go b/engine/agent/child_mode_inherit_test.go new file mode 100644 index 0000000000..1332145d39 --- /dev/null +++ b/engine/agent/child_mode_inherit_test.go @@ -0,0 +1,86 @@ +package agent_test + +import ( + "context" + "sync/atomic" + "testing" + "time" + + "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/session" + "github.com/stacklok/mecatl/engine/tool" +) + +// TestEffectiveChildMode pins the inheritance table: a default-configured child +// inherits an auto or yolo parent; other parents and explicitly configured +// child modes are kept. +func TestEffectiveChildMode(t *testing.T) { + for _, tc := range []struct { + configured, parent, want session.PermissionMode + }{ + {session.ModeDefault, session.ModeYolo, session.ModeYolo}, + {session.ModeDefault, session.ModeAuto, session.ModeAuto}, + {session.ModeDefault, session.ModeAccept, session.ModeDefault}, + {session.ModeDefault, session.ModePlan, session.ModeDefault}, + {session.ModeDefault, "", session.ModeDefault}, + {session.ModePlan, session.ModeYolo, session.ModePlan}, + {session.ModeAccept, session.ModeAuto, session.ModeAccept}, + } { + if got := agent.EffectiveChildModeForTest(tc.configured, tc.parent); got != tc.want { + t.Errorf("effectiveChildMode(%q, parent %q) = %q, want %q", tc.configured, tc.parent, got, tc.want) + } + } +} + +// TestSubagentInheritsYoloParentMode drives a real parent run: a child tool +// that asks under the default mode (no rules, headless → denied) runs when the +// parent session is in yolo, because the child inherits the parent's mode. +func TestSubagentInheritsYoloParentMode(t *testing.T) { + for _, tc := range []struct { + parent session.PermissionMode + want bool + }{ + {session.ModeDefault, false}, + {session.ModeYolo, true}, + } { + var executed atomic.Bool + childTool := &fakeTool{name: "Mutate", readOnly: false, + exec: func(_ context.Context, in session.ToolCall, _ tool.Workspace) (session.ToolResult, error) { + executed.Store(true) + return session.NewToolResult(in.ID, "ran"), nil + }} + childEngine := agent.NewEngine(agent.Deps{ + LLM: mockllm.New( + mockllm.ToolCallTurn(toolCall("k1", "Mutate", `{}`)), + mockllm.TextTurn("child done"), + ), + Catalog: catalogWith(t, childTool), + Policy: permpolicy.NewPolicy(nil, nil), + Model: "child-model", + }) + task := agent.NewSubagentTool(childEngine) + e := newEngine(agent.Deps{LLM: mockllm.New( + mockllm.ToolCallTurn(toolCall("p1", "Subagent", `{"prompt":"go"}`)), + mockllm.TextTurn("ok"), + ), Catalog: catalogWith(t, task)}) + sess := newSession(t, session.Limits{}) + if err := sess.SetMode(tc.parent); err != nil { + t.Fatal(err) + } + done := make(chan struct{}) + go func() { + drain(e.Run(context.Background(), sess, agent.MemEnv("/ws"), agent.RunRequest{Text: "go"})) + close(done) + }() + select { + case <-done: + case <-time.After(5 * time.Second): + t.Fatal("parent run did not complete") + } + if executed.Load() != tc.want { + t.Errorf("parent %s: child mutating tool executed=%t, want %t", tc.parent, executed.Load(), tc.want) + } + } +} diff --git a/engine/agent/dispatch.go b/engine/agent/dispatch.go index 88c57ea6cb..0a37f239ec 100644 --- a/engine/agent/dispatch.go +++ b/engine/agent/dispatch.go @@ -2140,6 +2140,7 @@ func (e *Engine) parentCaps(r *Run, sess *session.Session, turnIdx int, reporter // parentCaps.parentSessionID. caps.parentSessionID = sess.ID caps.parentIncarnation = sess.Incarnation() + caps.parentMode = sess.Mode } // The OPT-IN headless ask reviewer: bind the engine's reviewer + THIS run's // breaker + the timeout into a closure resolveChildAsk consults on the headless diff --git a/engine/agent/export_test.go b/engine/agent/export_test.go index 7571960550..6ccf375445 100644 --- a/engine/agent/export_test.go +++ b/engine/agent/export_test.go @@ -36,3 +36,6 @@ func RefreshReviewTasksForTest(r *Run, messages []session.Message) { func WithParallelBranchRegisteredForTest(fn func(int)) ParallelOption { return func(t *ParallelTool) { t.onBranchRegistered = fn } } + +// EffectiveChildModeForTest exposes the delegated-child mode rule. +var EffectiveChildModeForTest = effectiveChildMode diff --git a/engine/agent/parallel.go b/engine/agent/parallel.go index 0386f74ab8..3851605157 100644 --- a/engine/agent/parallel.go +++ b/engine/agent/parallel.go @@ -211,7 +211,8 @@ func WithParallelChildLimits(l session.Limits) ParallelOption { } // WithParallelChildMode sets the permission mode each child branch session runs under -// (default session.ModeDefault). +// (default session.ModeDefault, which inherits an auto or yolo parent's mode; see +// effectiveChildMode). func WithParallelChildMode(m session.PermissionMode) ParallelOption { return func(t *ParallelTool) { t.childMode = m } } @@ -1179,12 +1180,12 @@ func (t *ParallelTool) runBranch(ctx context.Context, callID session.ToolCallID, if caps.parentSessionID == "" { // Direct Tool.Execute has no parent aggregate identity. Classify that // custom-host path unknown rather than fabricating lineage or granting main. - childSess = newChildSessionInEnvironment(t.childSessionID("", callID, i), t.childMode, + childSess = newChildSessionInEnvironment(t.childSessionID("", callID, i), effectiveChildMode(t.childMode, caps.parentMode), childEnv, t.limits, branchEngine.now()) err = childSess.RestoreSessionMetadata(session.SessionKindUnknown, session.SessionRelationship{}) } else { childSess, err = newParallelBranchSessionInEnvironment( - t.childSessionID(caps.parentSessionID, callID, i), t.childMode, + t.childSessionID(caps.parentSessionID, callID, i), effectiveChildMode(t.childMode, caps.parentMode), childEnv, t.limits, branchEngine.now(), caps.parentSessionID, caps.parentIncarnation, callID, i) } diff --git a/engine/agent/subagent.go b/engine/agent/subagent.go index 27abf6439b..db3a1e74a6 100644 --- a/engine/agent/subagent.go +++ b/engine/agent/subagent.go @@ -80,6 +80,10 @@ type observableTool interface { // adapter/server/proto type crosses. A tool that does not implement childCapableTool // (or a nil caps) gets the legacy headless auto-deny posture, unchanged. type parentCaps struct { + // parentMode is the parent session's permission mode at dispatch. A child of + // an auto or yolo parent inherits that mode (effectiveChildMode) so the + // parent's mode-driven authority carries to its delegates. + parentMode session.PermissionMode // reviewRoot shares only harness-owned trajectory/reviewer state with workers. // It never carries a parent conversation or model-authored summary. reviewRoot *reviewRoot @@ -1013,12 +1017,26 @@ func WithChildLimits(l session.Limits) SubagentOption { } // WithChildMode sets the permission mode the child session runs under (default -// session.ModeDefault). session.ModePlan additionally hides any non-read-only +// session.ModeDefault, which inherits an auto or yolo parent's mode; see +// effectiveChildMode). session.ModePlan additionally hides any non-read-only // tools from the child at the catalog level. func WithChildMode(m session.PermissionMode) SubagentOption { return func(t *SubagentTool) { t.childMode = m } } +// effectiveChildMode is the mode a delegated child session runs in. A child +// configured with the default mode inherits an auto or yolo parent's mode, so +// the parent's mode-driven authority (allow-all, and in yolo the loosened +// substitution floor) carries to its delegates; plan, default, and accept-edits +// parents keep the configured child mode. An explicitly narrower configured +// mode (for example plan) is never widened. +func effectiveChildMode(configured, parent session.PermissionMode) session.PermissionMode { + if configured == session.ModeDefault && (parent == session.ModeAuto || parent == session.ModeYolo) { + return parent + } + return configured +} + // WithSubagentStopHook injects the HookRunner that fires the SubagentStop hook // when a child run finishes. It is best-effort: a hook error or block never fails // the Subagent call. Passing nil disables the hook. @@ -2261,7 +2279,7 @@ func (t *SubagentTool) resolveEngineAndLimits(callID session.ToolCallID, args su // still on disk — because this is the only place that sees the resumed session's // PERSISTED workspace before buildChildSession re-homes it. See editsSurvived's // doc-comment on the named result below and resumeWritableNote. -func (t *SubagentTool) prepareChildSession(ctx context.Context, call session.ToolCall, env tool.Environment, args subagentArgs, resuming, writable bool, childID, parentID session.SessionID, parentIncarnation session.IncarnationID, limits session.Limits, forkHistory []session.Message, forkInstructions session.InstructionSnapshot) (child *session.Session, runEnv tool.Environment, cleanup func() error, advisory string, editsSurvived bool, errResult session.ToolResult, ok bool) { +func (t *SubagentTool) prepareChildSession(ctx context.Context, call session.ToolCall, env tool.Environment, args subagentArgs, resuming, writable bool, childID, parentID session.SessionID, parentIncarnation session.IncarnationID, parentMode session.PermissionMode, limits session.Limits, forkHistory []session.Message, forkInstructions session.InstructionSnapshot) (child *session.Session, runEnv tool.Environment, cleanup func() error, advisory string, editsSurvived bool, errResult session.ToolResult, ok bool) { noop := func() error { return nil } var resumedChild *session.Session priorRef := session.EnvironmentRef{} @@ -2299,7 +2317,7 @@ func (t *SubagentTool) prepareChildSession(ctx context.Context, call session.Too // otherwise is the exact falsehood resumeWritableNote exists to prevent, inverted. // The path comparison is the honest test and needs no new persisted field. editsSurvived = writable && priorRef.Valid() && priorRef == env.Ref() - child, errRes, bok := t.buildChildSession(call.ID, childID, parentID, parentIncarnation, resumedChild, runEnv, limits, forkHistory, forkInstructions) + child, errRes, bok := t.buildChildSession(call.ID, childID, parentID, parentIncarnation, parentMode, resumedChild, runEnv, limits, forkHistory, forkInstructions) if !bok { _ = cleanupWS() return nil, tool.Environment{}, noop, "", false, errRes, false @@ -2580,7 +2598,7 @@ func (t *SubagentTool) run(ctx context.Context, call session.ToolCall, env tool. // Resume load + fork + session build (see prepareChildSession). The cleanup is // always non-nil and tears the worktree down after the child fully drains (the // run is drained below in this call), so a deferred cleanup is correct. - child, runEnv, cleanupWS, forkAdvisory, editsSurvived, errResult, ok := t.prepareChildSession(ctx, call, env, args, resuming, writable, childID, caps.parentSessionID, caps.parentIncarnation, limits, forkHistory, forkInstructions) + child, runEnv, cleanupWS, forkAdvisory, editsSurvived, errResult, ok := t.prepareChildSession(ctx, call, env, args, resuming, writable, childID, caps.parentSessionID, caps.parentIncarnation, caps.parentMode, limits, forkHistory, forkInstructions) if !ok { return errResult, nil } @@ -2967,7 +2985,7 @@ func (t *SubagentTool) driveBackground(ctx context.Context, b backgroundChild) { return } defer func() { _ = cleanupWS() }() - child, errResult, ok := t.buildChildSession(b.call.ID, b.childID, b.caps.parentSessionID, b.caps.parentIncarnation, b.resumed, runEnv, b.limits, b.forkHistory, b.forkInstructions) + child, errResult, ok := t.buildChildSession(b.call.ID, b.childID, b.caps.parentSessionID, b.caps.parentIncarnation, b.caps.parentMode, b.resumed, runEnv, b.limits, b.forkHistory, b.forkInstructions) if !ok { endOnError(errResult) return @@ -4186,7 +4204,7 @@ func (t *SubagentTool) forkChildEnvironment(ctx context.Context, callID session. // torn down, and without the re-home the re-persisted snapshot would record a dead // path. (The child's prompt cwd is independently sourced from the engine's PromptConfig // and is NOT affected by this field.) -func (t *SubagentTool) buildChildSession(callID session.ToolCallID, childID, parentID session.SessionID, parentIncarnation session.IncarnationID, resumedChild *session.Session, env tool.Environment, limits session.Limits, forkHistory []session.Message, forkInstructions session.InstructionSnapshot) (*session.Session, session.ToolResult, bool) { +func (t *SubagentTool) buildChildSession(callID session.ToolCallID, childID, parentID session.SessionID, parentIncarnation session.IncarnationID, parentMode session.PermissionMode, resumedChild *session.Session, env tool.Environment, limits session.Limits, forkHistory []session.Message, forkInstructions session.InstructionSnapshot) (*session.Session, session.ToolResult, bool) { if resumedChild == nil { // When a named agent def pins limits, the child runs under THOSE; otherwise it uses // the Subagent tool's default limits. @@ -4195,10 +4213,10 @@ func (t *SubagentTool) buildChildSession(callID session.ToolCallID, childID, par if parentID == "" { // Direct Tool.Execute has no parent aggregate identity. Classify that // custom-host path unknown rather than fabricating lineage or granting main. - child = newChildSessionInEnvironment(childID, t.childMode, env, limits, t.childEngine.now()) + child = newChildSessionInEnvironment(childID, effectiveChildMode(t.childMode, parentMode), env, limits, t.childEngine.now()) err = child.RestoreSessionMetadata(session.SessionKindUnknown, session.SessionRelationship{}) } else { - child, err = newSubagentSessionInEnvironment(childID, t.childMode, env, limits, t.childEngine.now(), parentID, parentIncarnation, callID) + child, err = newSubagentSessionInEnvironment(childID, effectiveChildMode(t.childMode, parentMode), env, limits, t.childEngine.now(), parentID, parentIncarnation, callID) } if err != nil { return nil, session.NewToolError(callID, diff --git a/engine/agent/teamtool.go b/engine/agent/teamtool.go index 7d43f6bfb6..43f6483b43 100644 --- a/engine/agent/teamtool.go +++ b/engine/agent/teamtool.go @@ -403,6 +403,11 @@ func (t *TeamTool) run(ctx context.Context, call session.ToolCall, env tool.Envi // ask can surface and each member's durable relationship is correlated before it // is registered, persisted, or projected. opts = append(opts, withParentCaps(caps), withParentTeamCall(call.ID)) + // Members of an auto or yolo parent inherit its mode (effectiveChildMode); a + // member definition's own permissionMode still overrides the team default. + if mode := effectiveChildMode(session.ModeDefault, caps.parentMode); mode != session.ModeDefault { + opts = append(opts, WithTeamMode(mode)) + } sup := NewSupervisor(tm, env, factory, opts...) roster := teamRoster(args.Members) diff --git a/internal/adapter/acp/agent.go b/internal/adapter/acp/agent.go index ebe3cc08ad..ff1c287336 100644 --- a/internal/adapter/acp/agent.go +++ b/internal/adapter/acp/agent.go @@ -265,8 +265,8 @@ func (a *Agent) handleInitialize(params json.RawMessage) (any, error) { // Client-provided streaming-HTTP MCP servers are validated and mounted PER-SESSION (so // their tools and auth never leak into other sessions). A stdio (command-shaped) // entry and an sse entry are hard-rejected (CLAUDE.md: no stdio MCP, ever; mecatl -// never spawns a server process). The session mode is always default this phase; -// the available modes are reflected so the editor can show them. +// never spawns a server process). The session starts in the server's default +// mode; the admitted modes are reflected so the editor can show them. func (a *Agent) handleSessionNew(ctx context.Context, params json.RawMessage) (any, error) { var req newSessionRequest if err := json.Unmarshal(params, &req); err != nil { @@ -293,7 +293,9 @@ func (a *Agent) handleSessionNew(ctx context.Context, params json.RawMessage) (a return tool.NewEnvironment(base.Ref(), ws, base.ReadLedger(), nil) } } - sess, err := a.svc.CreateACPSession(ctx, req.Cwd, session.ModeDefault, session.Limits{}, specs, overlay) + // An empty mode applies the server's configured default mode, exactly as an + // unspecified CreateSession does on gRPC and HTTP. + sess, err := a.svc.CreateACPSession(ctx, req.Cwd, "", session.Limits{}, specs, overlay) if err != nil { return nil, newMethodErr(codeInvalidParams, "acp: session/new: "+err.Error()) } @@ -308,22 +310,30 @@ func (a *Agent) handleSessionNew(ctx context.Context, params json.RawMessage) (a return newSessionResponse{ SessionID: string(sess.ID), - Modes: modeStateFor(sess.Mode), + Modes: a.modeStateFor(sess.Mode), }, nil } -// modeStateFor builds the ACP sessionModeState advertising mecatl's three -// permission modes with current as the session's CURRENT mode. It is shared by -// session/new and session/load so both seed the editor's mode picker identically. -func modeStateFor(current session.PermissionMode) *sessionModeState { - return &sessionModeState{ - CurrentModeID: string(current), - AvailableModes: []sessionMode{ - {ID: string(session.ModeDefault), Name: "Default", Description: "Standard deny/ask/allow permissions"}, - {ID: string(session.ModePlan), Name: "Plan", Description: "Read-only planning (no mutations)"}, - {ID: string(session.ModeAccept), Name: "Accept Edits", Description: "Auto-accept edits"}, - }, +// acpModes names and describes every mecatl permission mode an editor may be +// offered, in plan → yolo order. +var acpModes = map[session.PermissionMode]sessionMode{ + session.ModePlan: {ID: string(session.ModePlan), Name: "Plan", Description: "Read-only planning (no mutations)"}, + session.ModeDefault: {ID: string(session.ModeDefault), Name: "Default", Description: "Standard deny/ask/allow permissions"}, + session.ModeAccept: {ID: string(session.ModeAccept), Name: "Accept Edits", Description: "Auto-accept edits"}, + session.ModeAuto: {ID: string(session.ModeAuto), Name: "Auto", Description: "Run tools without asking, with an enforcing guardrails checker"}, + session.ModeYolo: {ID: string(session.ModeYolo), Name: "YOLO", Description: "Run tools without asking and without a preventive checker"}, +} + +// modeStateFor builds the ACP sessionModeState with current as the session's +// CURRENT mode, advertising only the modes the server admits now (its ceiling +// and the auto checker requirement), so the editor's picker never offers a +// mode session/set_mode would refuse. Shared by session/new and session/load. +func (a *Agent) modeStateFor(current session.PermissionMode) *sessionModeState { + state := &sessionModeState{CurrentModeID: string(current)} + for _, mode := range a.svc.AdmittedModes() { + state.AvailableModes = append(state.AvailableModes, acpModes[mode]) } + return state } // notifyAvailableCommands lists the slash commands for the workspace via the @@ -419,7 +429,7 @@ func (a *Agent) handleSessionLoad(ctx context.Context, params json.RawMessage) ( // Rebuild the editor's transcript from the persisted history BEFORE returning, // so a re-attaching editor sees the prior turns rather than an empty session. a.replayHistory(ctx, req.SessionID, sess.Conversation) - return loadSessionResponse{Modes: modeStateFor(sess.Mode)}, nil + return loadSessionResponse{Modes: a.modeStateFor(sess.Mode)}, nil } // handleSetMode applies a session/set_mode by mapping the ACP modeId to a mecatl @@ -467,6 +477,10 @@ func modeFromACP(modeID string) (session.PermissionMode, bool) { return session.ModePlan, true case session.ModeAccept: return session.ModeAccept, true + case session.ModeAuto: + return session.ModeAuto, true + case session.ModeYolo: + return session.ModeYolo, true default: return "", false } diff --git a/internal/adapter/acp/mode_admission_test.go b/internal/adapter/acp/mode_admission_test.go new file mode 100644 index 0000000000..2b837d7972 --- /dev/null +++ b/internal/adapter/acp/mode_admission_test.go @@ -0,0 +1,63 @@ +package acp_test + +import ( + "encoding/json" + "slices" + "testing" + + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +// TestACPModesFollowServerAdmission pins that ACP starts a session in the +// server's default mode and offers exactly the modes the server admits: the +// ceiling bounds the list, and auto appears only with an enforcing checker. +func TestACPModesFollowServerAdmission(t *testing.T) { + for _, tc := range []struct { + name string + def, ceil session.PermissionMode + checker bool + wantModes []string + wantCurrent string + }{ + {"strict ceiling", session.ModeDefault, session.ModeAccept, false, []string{"plan", "default", "acceptEdits"}, "default"}, + {"yolo without checker", session.ModeYolo, session.ModeYolo, false, []string{"plan", "default", "acceptEdits", "yolo"}, "yolo"}, + {"auto with checker", session.ModeAuto, session.ModeAuto, true, []string{"plan", "default", "acceptEdits", "auto"}, "auto"}, + } { + t.Run(tc.name, func(t *testing.T) { + svc := newServiceCfg(t, mockllm.New(), allowRules(), func(c *server.Config) { + c.DefaultMode, c.MaxAllowedMode, c.EnforcingCheckerConfigured = tc.def, tc.ceil, tc.checker + }) + e, cleanup := startAgent(t, svc) + defer cleanup() + res := e.call("session/new", map[string]any{"cwd": testCWD(t), "mcpServers": []any{}}) + var ns struct { + SessionID string `json:"sessionId"` + Modes struct { + CurrentModeID string `json:"currentModeId"` + AvailableModes []struct { + ID string `json:"id"` + } `json:"availableModes"` + } `json:"modes"` + } + if err := json.Unmarshal(res, &ns); err != nil { + t.Fatalf("session/new: %s: %v", res, err) + } + var got []string + for _, m := range ns.Modes.AvailableModes { + got = append(got, m.ID) + } + if !slices.Equal(got, tc.wantModes) || ns.Modes.CurrentModeID != tc.wantCurrent { + t.Fatalf("modes = %v current %q, want %v current %q", got, ns.Modes.CurrentModeID, tc.wantModes, tc.wantCurrent) + } + last := tc.wantModes[len(tc.wantModes)-1] + e.call("session/set_mode", map[string]any{"sessionId": ns.SessionID, "modeId": "plan"}) + e.call("session/set_mode", map[string]any{"sessionId": ns.SessionID, "modeId": last}) + sess, err := svc.GetSession(t.Context(), session.SessionID(ns.SessionID)) + if err != nil || string(sess.Mode) != last { + t.Fatalf("set_mode %s: mode %v err %v", last, sess, err) + } + }) + } +} diff --git a/internal/adapter/permconfig/schema.go b/internal/adapter/permconfig/schema.go index b60b8a7963..b468406699 100644 --- a/internal/adapter/permconfig/schema.go +++ b/internal/adapter/permconfig/schema.go @@ -166,9 +166,10 @@ type Config struct { // reads the scalar. Posture string `yaml:"posture"` // PermissionMode is the OPERATOR-TIER named permission-mode token - // (plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets - // the posture and the default session mode together and supersedes the - // deprecated posture: key. Like Posture it is honoured ONLY from the + // (plan/default/accept-edits/auto/yolo). It sets the mode new sessions start in + // and the server ceiling (the most permissive mode a session may switch to) + // together, and supersedes the deprecated posture: key. It never grants + // workspace trust. Like Posture it is honoured ONLY from the // user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. // Empty = absent. The composition layer parses the token. PermissionMode string `yaml:"permissionMode"` diff --git a/internal/adapter/server/classification.go b/internal/adapter/server/classification.go index 313cbac503..cf265b9db7 100644 --- a/internal/adapter/server/classification.go +++ b/internal/adapter/server/classification.go @@ -359,6 +359,7 @@ var serviceAccessTable = map[string]ClassificationEntry{ // --- shared infrastructure: process-wide catalog/config, same for every caller by design --- "CompatibilityInfo": {KindCallerOwned, "projects broker inspection only for the verified caller carried in ctx; the remaining deployment capabilities are shared and no session record is read"}, + "AdmittedModes": {KindSharedInfrastructure, "reports the deployment-wide permission-mode ceiling and checker requirement, identical for every caller; it reads no session record"}, "ClientMCPFromWire": {KindSharedInfrastructure, "classifies a request's MCP entries and applies the deployment-wide client-MCP policy, which is identical for every caller; it reads and writes no session, schedule, or memory record and reaches no network"}, "ListMcpResources": {KindSharedInfrastructure, "MCP servers are process-wide composition config, not a caller-owned record; every caller may list a wired server's resources"}, "ReadMcpResource": {KindSharedInfrastructure, "reads a resource off a process-wide MCP server registration, not a caller-owned record"}, diff --git a/internal/adapter/server/compatibility_info_test.go b/internal/adapter/server/compatibility_info_test.go index a8456ceea5..0bc746e807 100644 --- a/internal/adapter/server/compatibility_info_test.go +++ b/internal/adapter/server/compatibility_info_test.go @@ -158,6 +158,65 @@ func TestSDKServerEnablers_Scenario1_CompatibilityInfoTransportParity(t *testing } } +// TestCompatibilityInfoSubagentAskReviewerTransportParity pins that the +// optional subagent_ask_reviewer capability stays unset when the server does +// not report it and carries the exact state when it does, over gRPC and HTTP. +func TestCompatibilityInfoSubagentAskReviewerTransportParity(t *testing.T) { + for _, reviewer := range []*string{nil, new("on"), new("off"), new("inert")} { + engine := agent.NewEngine(agent.Deps{ + LLM: mockllm.New(mockllm.TextTurn("ok")), + Catalog: tool.NewCatalog(), + Policy: permpolicy.NewPolicy(nil, nil), + Model: "test-model", + }) + svc, err := newPlacementTestService(server.Config{ + Engine: engine, + Store: memstore.New(), + Now: func() time.Time { return time.Unix(0, 0) }, + SubagentAskReviewer: reviewer, + }) + if err != nil { + t.Fatalf("new service: %v", err) + } + client, cleanup := dialGRPC(t, svc) + srv := httptest.NewServer(server.NewHTTPHandler(svc)) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + viaGRPC, err := client.GetCompatibilityInfo(ctx, &mecatlv1.GetCompatibilityInfoRequest{}) + if err != nil { + t.Fatalf("GetCompatibilityInfo (grpc): %v", err) + } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/v1/compatibility", nil) + if err != nil { + t.Fatalf("new request: %v", err) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("GET /v1/compatibility: %v", err) + } + raw, err := io.ReadAll(resp.Body) + _ = resp.Body.Close() + cancel() + srv.Close() + cleanup() + if err != nil { + t.Fatalf("read body: %v", err) + } + var viaHTTP mecatlv1.GetCompatibilityInfoResponse + if err := json.Unmarshal(raw, &viaHTTP); err != nil { + t.Fatalf("decode HTTP body: %v: %s", err, raw) + } + for transport, caps := range map[string]*mecatlv1.ServerCapabilities{"grpc": viaGRPC.GetCapabilities(), "http": viaHTTP.GetCapabilities()} { + switch { + case reviewer == nil && caps.SubagentAskReviewer != nil: + t.Errorf("%s: subagent_ask_reviewer = %q, want unset", transport, caps.GetSubagentAskReviewer()) + case reviewer != nil && caps.GetSubagentAskReviewer() != *reviewer: + t.Errorf("%s: subagent_ask_reviewer = %v, want %q", transport, caps.SubagentAskReviewer, *reviewer) + } + } + } +} + // TestFeatureRegistryIsSingleSource is AC1.4. // // The feature set is non-empty, sorted, duplicate-free, and identical on both diff --git a/internal/adapter/server/features.go b/internal/adapter/server/features.go index 46e44f4329..7315b162bc 100644 --- a/internal/adapter/server/features.go +++ b/internal/adapter/server/features.go @@ -86,6 +86,14 @@ const ( // FeatureSessionAgentDefinitions reports root agent-definition binding on both // create transports, independent of whether any definitions are configured. FeatureSessionAgentDefinitions = "session_agent_definitions" + // FeatureSessionPermissionModes reports the five session-scoped permission + // modes (plan, default, accept-edits, auto, yolo): AUTO and YOLO are valid on + // CreateSession, SetMode, and session reads; each mode's authority applies + // per session within the server ceiling; and an unspecified CreateSession + // mode resolves to the server's configured default. The legacy posture + // capability cannot answer this: an older server advertises auto/yolo + // posture without supporting these session modes. + FeatureSessionPermissionModes = "session_permission_modes" ) // FeatureScope is what the DEPLOYMENT permits, as distinct from what the build @@ -126,6 +134,7 @@ var allFeatures = []string{ FeatureServerInfo, FeatureSessionActivityInventory, FeatureSessionAgentDefinitions, + FeatureSessionPermissionModes, FeatureSkillFiles, FeatureWatchSessionEvents, } diff --git a/internal/adapter/server/mode_admission_test.go b/internal/adapter/server/mode_admission_test.go index 7a24541a26..61d18c225f 100644 --- a/internal/adapter/server/mode_admission_test.go +++ b/internal/adapter/server/mode_admission_test.go @@ -18,6 +18,7 @@ import ( "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/port" "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/engine/tool" "github.com/stacklok/mecatl/internal/adapter/server" @@ -27,15 +28,21 @@ import ( // ceiling, default mode, and enforcing-checker state. func modeAdmissionService(t *testing.T, ceiling, defaultMode session.PermissionMode, checker bool) *server.Service { t.Helper() - llm := mockllm.New() - svc, err := newPlacementTeamTestService(server.Config{ + return modeAdmissionServiceOn(t, memstore.New(), mockllm.New(), ceiling, defaultMode, checker) +} + +// modeAdmissionServiceOn is modeAdmissionService over an explicit store and +// provider, so a test can model a deployment restart over persisted sessions. +func modeAdmissionServiceOn(t *testing.T, store port.SessionStore, llm *mockllm.Provider, ceiling, defaultMode session.PermissionMode, checker bool) *server.Service { + t.Helper() + svc, err := newPlacementTestService(server.Config{ Engine: agent.NewEngine(agent.Deps{ LLM: llm, Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(allowRules(), nil), Model: "test-model", }), - Store: memstore.New(), + Store: store, PlacementProvider: testPlacementProvider{}, PlacementScope: "test", Now: func() time.Time { return time.Unix(0, 0) }, @@ -145,24 +152,114 @@ func TestGRPCModeAdmissionRefusals(t *testing.T) { } } -// TestOperatorDefaultAutoAdmittedWithoutChecker pins that the operator's -// configured default mode stays admissible without an enforcing checker (the -// operator chose it; startup WARNs), both for an unspecified create and for -// an explicit request of that same mode. -func TestOperatorDefaultAutoAdmittedWithoutChecker(t *testing.T) { - svc := modeAdmissionService(t, session.ModeAuto, session.ModeAuto, false) +// TestAutoDefaultWithoutCheckerRefusedAtConstruction pins that auto has no +// default-mode exemption: a service whose default is auto refuses to start +// without an enforcing checker, and starts with one. +func TestAutoDefaultWithoutCheckerRefusedAtConstruction(t *testing.T) { + _, err := newPlacementTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(nil, nil), Model: "test-model"}), + Store: memstore.New(), + PlacementProvider: testPlacementProvider{}, + PlacementScope: "test", + DefaultMode: session.ModeAuto, + MaxAllowedMode: session.ModeAuto, + }) + if !errors.Is(err, server.ErrConfig) || !strings.Contains(err.Error(), "enforcing guardrails checker") { + t.Fatalf("auto default without checker: err = %v, want ErrConfig naming the checker", err) + } + svc := modeAdmissionService(t, session.ModeAuto, session.ModeAuto, true) + sess, err := svc.CreateSession(context.Background(), "", session.Limits{}) + if err != nil || sess.Mode != session.ModeAuto { + t.Fatalf("auto default with checker: mode %v, err %v", sess, err) + } +} + +// TestAutoRequiresCheckerEvenWhenNotDefault pins that, without an enforcing +// checker, explicit auto creation and switching (back) to auto are refused on +// every ceiling that would otherwise admit auto, while yolo stays admissible. +func TestAutoRequiresCheckerEvenWhenNotDefault(t *testing.T) { ctx := context.Background() - for _, mode := range []session.PermissionMode{"", session.ModeAuto} { - sess, err := svc.CreateSession(ctx, mode, session.Limits{}) + for _, def := range []session.PermissionMode{session.ModeDefault, session.ModeYolo} { + svc := modeAdmissionService(t, session.ModeYolo, def, false) + if _, err := svc.CreateSession(ctx, session.ModeAuto, session.Limits{}); !errors.Is(err, server.ErrInvalidArgument) { + t.Fatalf("default %s: CreateSession(auto) err = %v, want ErrInvalidArgument", def, err) + } + sess, err := svc.CreateSession(ctx, "", session.Limits{}) if err != nil { - t.Fatalf("CreateSession(%q): %v", mode, err) + t.Fatalf("default %s: CreateSession: %v", def, err) + } + if _, err := svc.SetMode(ctx, sess.ID, session.ModeAuto); !errors.Is(err, server.ErrInvalidArgument) { + t.Fatalf("default %s: SetMode(auto) err = %v, want ErrInvalidArgument", def, err) } - if sess.Mode != session.ModeAuto { - t.Fatalf("CreateSession(%q) mode = %q, want auto", mode, sess.Mode) + if _, err := svc.SetMode(ctx, sess.ID, session.ModeYolo); err != nil { + t.Fatalf("default %s: SetMode(yolo) positive control: %v", def, err) } } } +// TestStoredModeReadmittedAfterTighterRestart persists a permissive session, +// reopens the store under a tighter deployment, and proves prompt, fork, and +// clear refuse BEFORE any provider work, without touching the session; a +// SetMode to an admitted mode then lets the same session continue. +func TestStoredModeReadmittedAfterTighterRestart(t *testing.T) { + ctx := context.Background() + for _, tc := range []struct { + name string + stored session.PermissionMode + ceiling session.PermissionMode + checker bool + }{ + {"yolo above default ceiling", session.ModeYolo, session.ModeAccept, true}, + {"auto above default ceiling", session.ModeAuto, session.ModeAccept, true}, + {"auto after checker removed", session.ModeAuto, session.ModeYolo, false}, + } { + t.Run(tc.name, func(t *testing.T) { + store := memstore.New() + loose := modeAdmissionServiceOn(t, store, mockllm.New(), session.ModeYolo, session.ModeDefault, true) + sess, err := loose.CreateSession(ctx, tc.stored, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession(%s) on loose deployment: %v", tc.stored, err) + } + + llm := mockllm.New(mockllm.TextTurn("ran")) + tight := modeAdmissionServiceOn(t, store, llm, tc.ceiling, session.ModeDefault, tc.checker) + if run, err := tight.StartRun(ctx, sess.ID, "go"); !errors.Is(err, server.ErrFailedPrecondition) || run != nil { + t.Fatalf("StartRun = run %v, err %v; want ErrFailedPrecondition", run, err) + } + if _, err := tight.ForkSessionSuccessor(ctx, server.ForkSuccessorRequest{Source: sess.ID}); !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("ForkSessionSuccessor err = %v, want ErrFailedPrecondition", err) + } + if _, err := tight.ClearSessionSuccessor(ctx, sess.ID, server.SuccessorPlacement{}); !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("ClearSessionSuccessor err = %v, want ErrFailedPrecondition", err) + } + if llm.Calls() != 0 { + t.Fatalf("provider called %d time(s) before refusal, want 0", llm.Calls()) + } + kept, err := store.Load(ctx, sess.ID) + if err != nil { + t.Fatalf("Load: %v", err) + } + if kept.Mode != tc.stored || kept.State != sess.State { + t.Fatalf("refusal mutated the session: mode %q state %q", kept.Mode, kept.State) + } + + if _, err := tight.SetMode(ctx, sess.ID, session.ModeDefault); err != nil { + t.Fatalf("SetMode(default): %v", err) + } + run, err := tight.StartRun(ctx, sess.ID, "go") + if err != nil { + t.Fatalf("StartRun after SetMode(default): %v", err) + } + for range run.Events() { + } + tight.FinishRun(sess.ID, run) + if llm.Calls() != 1 { + t.Fatalf("provider calls after re-admission = %d, want 1", llm.Calls()) + } + }) + } +} + // TestHTTPAutoYoloModes pins the HTTP mode mapping and the shared admission. func TestHTTPAutoYoloModes(t *testing.T) { decode := func(resp *http.Response) (int, string) { diff --git a/internal/adapter/server/placement_successor.go b/internal/adapter/server/placement_successor.go index d31c1d3494..5afd1e8f63 100644 --- a/internal/adapter/server/placement_successor.go +++ b/internal/adapter/server/placement_successor.go @@ -160,6 +160,11 @@ func (s *Service) createPlacedSuccessorLocked(ctx context.Context, req ForkSucce if err != nil || absent { return "", err } + // The successor inherits source.Mode, so it must be admissible under the + // current deployment before anything (including clearing the source) happens. + if err := s.admitStoredMode(source); err != nil { + return "", err + } if copyHistory { if err := s.attachLiveInstructions(source, false); err != nil { return "", err diff --git a/internal/adapter/server/resume_awaiting_test.go b/internal/adapter/server/resume_awaiting_test.go index e165082ef6..d53c55432e 100644 --- a/internal/adapter/server/resume_awaiting_test.go +++ b/internal/adapter/server/resume_awaiting_test.go @@ -215,6 +215,59 @@ func TestApproveAfterRestartResumesAwaiting(t *testing.T) { } } +// TestApproveAfterTighterRestartRefusesStoredMode pins that an awaiting session +// persisted in a mode the restarted deployment no longer admits cannot resume +// through Approve: the refusal precedes provider and tool work and leaves the +// pending ask in place. +func TestApproveAfterTighterRestartRefusesStoredMode(t *testing.T) { + ctx := context.Background() + store := memstore.New() + var ran1 atomic.Int64 + svc1 := newAskingService(t, store, permstore.New(), &ran1, + mockllm.New(mockllm.ToolCallTurn(session.NewToolCall("w1", "Write", json.RawMessage(`{"path":"a.go"}`)))), false) + sess, err := svc1.CreateSession(ctx, session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + askID := driveServiceToAwaiting(t, svc1, sess.ID) + // Model a snapshot written under a looser deployment that admitted yolo. + parked, err := store.Load(ctx, sess.ID) + if err != nil { + t.Fatal(err) + } + parked.Mode = session.ModeYolo + if err := store.Save(ctx, parked); err != nil { + t.Fatal(err) + } + + var ran2 atomic.Int64 + cat := tool.NewCatalog() + cat.MustRegister(&writeAskTool{ran: &ran2}) + llm := mockllm.New(mockllm.TextTurn("done after approval")) + svc2, err := newPlacementTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{LLM: llm, Catalog: cat, Policy: permpolicy.NewPolicy(nil, permstore.New()), Model: "test-model", Store: store}), + Store: store, + Now: func() time.Time { return time.Unix(0, 0) }, + MaxAllowedMode: session.ModeAccept, + }) + if err != nil { + t.Fatalf("new service: %v", err) + } + if run, err := svc2.ApproveRun(ctx, sess.ID, askID, session.VerdictAllowOnce, ""); !errors.Is(err, server.ErrFailedPrecondition) || run != nil { + t.Fatalf("ApproveRun = run %v, err %v; want ErrFailedPrecondition", run, err) + } + if ran2.Load() != 0 || llm.Calls() != 0 { + t.Fatalf("work started before refusal: tool executions %d, provider calls %d", ran2.Load(), llm.Calls()) + } + kept, err := store.Load(ctx, sess.ID) + if err != nil { + t.Fatal(err) + } + if pending, ok := kept.PendingAsk(); kept.State != session.StateAwaiting || !ok || pending.AskID != askID { + t.Fatalf("refusal consumed the pending ask: state %s present %t", kept.State, ok) + } +} + // TestApproveNonAwaitingYieldsNoActiveRun is the state-gate mutation oracle: a // COMPLETED (terminal, non-awaiting) session resumed via Approve yields // ErrNoActiveRun and is NOT re-entered. Dropping the State!=StateAwaiting gate in diff --git a/internal/adapter/server/sdk_typescript_release_test.go b/internal/adapter/server/sdk_typescript_release_test.go index 669d093aad..3aaf12cc33 100644 --- a/internal/adapter/server/sdk_typescript_release_test.go +++ b/internal/adapter/server/sdk_typescript_release_test.go @@ -202,6 +202,7 @@ func TestSDKTypescriptRelease_Scenario1_PublicServiceProjectionParity(t *testing // call ResolveScopedRunAsk for guardrail-scoped asks. "ResolveApprovalRun", "ResolveScopedRunAsk", + "AdmittedModes", "BindPlacement", "CanProcessSchedule", "Cancel", diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index c73f01b5e0..fc45aad600 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -656,6 +656,10 @@ type Config struct { // workspace, projected into the ServerCapabilities echo as CHROME ONLY. nil // (an unconfigured child service) leaves the echo unset. ProjectTrusted *bool + // SubagentAskReviewer is the headless subagent ask reviewer state ("on", + // "off", "inert"), projected into the ServerCapabilities echo. nil (an + // unconfigured child service) leaves the echo unset. + SubagentAskReviewer *string // DeploymentID is an optional, opaque, operator-set label for this deployment, // surfaced on GetServerInfo. It is empty by default and is NEVER derived from // hostname, pod name, or environment: infrastructure topology is not something @@ -1695,8 +1699,8 @@ func NewService(cfg Config) (*Service, error) { return nil, err } cfg.ServerImplementation = normalizeServerImplementation(cfg.ServerImplementation) - if cfg.DefaultMode == "" { - cfg.DefaultMode = session.ModeDefault + if err := normalizeDefaultMode(&cfg); err != nil { + return nil, err } if cfg.Now == nil { cfg.Now = time.Now @@ -3275,22 +3279,23 @@ func (s *Service) capabilities() *mecatlv1.ServerCapabilities { // matches the client's documented semantics ("true when ≥1 provider is // available"); opening the picker fires ListModels, which runs the refresher // and populates the list, and the empty-list state is handled gracefully. - ModelSelection: len(s.currentModels()) > 0 || s.modelsRefresher.Load() != nil, - Memory: has(memory.RememberToolName), - Skills: has(skills.ToolName), - Shell: has(tool.ShellToolName), - Image: pcaps.Image, - Audio: pcaps.Audio, - Posture: s.cfg.Posture, - ProjectTrusted: s.cfg.ProjectTrusted, - Worktrees: s.placementDiscoveryAvailable(), - Reflection: s.cfg.ReflectSession != nil, - LearningProposals: s.cfg.Proposals != nil, - LearnedSkills: s.cfg.LearnedSkills != nil, - Scheduling: s.scheduleStore() != nil, - StorageHealth: s.cfg.StorageManagementAuthorized != nil && (implementsStorageHealth(s.cfg.Store) || s.scheduleStore() != nil), - StorageCleanup: s.cfg.StorageManagementAuthorized != nil && s.maintenanceMutationAvailable() && supportsCleanupDelete(s.cfg.Store), - ManualDream: toProtoDreamCapabilities(s.ManualDreamCapabilities()), + ModelSelection: len(s.currentModels()) > 0 || s.modelsRefresher.Load() != nil, + Memory: has(memory.RememberToolName), + Skills: has(skills.ToolName), + Shell: has(tool.ShellToolName), + Image: pcaps.Image, + Audio: pcaps.Audio, + Posture: s.cfg.Posture, + ProjectTrusted: s.cfg.ProjectTrusted, + SubagentAskReviewer: s.cfg.SubagentAskReviewer, + Worktrees: s.placementDiscoveryAvailable(), + Reflection: s.cfg.ReflectSession != nil, + LearningProposals: s.cfg.Proposals != nil, + LearnedSkills: s.cfg.LearnedSkills != nil, + Scheduling: s.scheduleStore() != nil, + StorageHealth: s.cfg.StorageManagementAuthorized != nil && (implementsStorageHealth(s.cfg.Store) || s.scheduleStore() != nil), + StorageCleanup: s.cfg.StorageManagementAuthorized != nil && s.maintenanceMutationAvailable() && supportsCleanupDelete(s.cfg.Store), + ManualDream: toProtoDreamCapabilities(s.ManualDreamCapabilities()), // Steer reads the SAME wired engine knob the runs consult (Deps.EnableSteer // via Engine.SteerEnabled) — the advertisement can never claim a steer // path the engine did not arm, and it is computed HERE, once, never @@ -4824,9 +4829,9 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio // admitMode is the single admission check for a caller-requested session mode, // shared by CreateSession, SetMode, and schedule fires (which create through // CreateSession). A mode above the server ceiling is refused, and auto requires -// an enforcing guardrails checker. The operator-configured DefaultMode is -// always admissible: the operator chose it at startup (where a missing checker -// is narrated as a WARN), so a session may start in it and return to it. +// an enforcing guardrails checker with no exemption: unchecked autonomy is yolo. +// admitStoredMode applies the same check to a persisted session at every run +// entry, so a mode admitted under an earlier, looser deployment cannot execute. func (s *Service) admitMode(mode session.PermissionMode) error { if modeRank(mode) == 0 { return fmt.Errorf("%w: unknown permission mode %q", ErrInvalidArgument, mode) @@ -4834,12 +4839,49 @@ func (s *Service) admitMode(mode session.PermissionMode) error { if s.cfg.MaxAllowedMode != "" && !modeWithinCeiling(mode, s.cfg.MaxAllowedMode) { return fmt.Errorf("%w: mode %q exceeds the server ceiling %q; the server must be relaunched with a higher --permission-mode to allow it", ErrInvalidArgument, mode, s.cfg.MaxAllowedMode) } - if mode == session.ModeAuto && mode != s.cfg.DefaultMode && !s.hasEnforcingChecker() { + if mode == session.ModeAuto && !s.hasEnforcingChecker() { return fmt.Errorf("%w: mode %q requires an enforcing guardrails checker; configure one with --guardrails-model or bind the guardrail model slot, or use yolo for gate-free autonomous operation", ErrInvalidArgument, mode) } return nil } +// normalizeDefaultMode defaults an empty DefaultMode to default and refuses +// an auto default without an enforcing checker: auto has no default-mode +// exemption. +func normalizeDefaultMode(cfg *Config) error { + if cfg.DefaultMode == "" { + cfg.DefaultMode = session.ModeDefault + } + if cfg.DefaultMode == session.ModeAuto && !cfg.EnforcingCheckerConfigured { + return fmt.Errorf("%w: default mode %q requires an enforcing guardrails checker; configure one or use yolo for unchecked autonomous operation", ErrConfig, cfg.DefaultMode) + } + return nil +} + +// AdmittedModes lists, in plan → yolo order, the permission modes this server +// admits for a session right now (the ceiling and the auto checker +// requirement), so a client can offer exactly the modes SetMode will accept. +func (s *Service) AdmittedModes() []session.PermissionMode { + var out []session.PermissionMode + for _, mode := range []session.PermissionMode{session.ModePlan, session.ModeDefault, session.ModeAccept, session.ModeAuto, session.ModeYolo} { + if s.admitMode(mode) == nil { + out = append(out, mode) + } + } + return out +} + +// admitStoredMode re-admits a persisted session's mode against the CURRENT +// ceiling and checker before execution, approval resume, or successor +// publication. A refusal leaves the session and its history untouched; the +// owner can SetMode to an admitted mode and continue. +func (s *Service) admitStoredMode(sess *session.Session) error { + if err := s.admitMode(sess.Mode); err != nil { + return fmt.Errorf("%w: session %q is in permission mode %q, which this server does not admit (%v); switch it to an admitted mode with SetMode to continue", ErrFailedPrecondition, sess.ID, sess.Mode, err) + } + return nil +} + // modeWithinCeiling reports whether mode is at or below ceiling in the // permission-mode ordering: plan < default < accept-edits < auto < yolo. func modeWithinCeiling(mode, ceiling session.PermissionMode) bool { @@ -9317,6 +9359,11 @@ 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) { + // Every run entry (prompt, approval resume, plan continuation, retry) passes + // here before any lease, engine, provider, or tool work. + if err := s.admitStoredMode(sess); err != nil { + return nil, nil, err + } operationRelease := func() {} if s.cfg.OperationPin != nil { var err error diff --git a/internal/app/build.go b/internal/app/build.go index 932ba3f56c..8473e2b374 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -2112,7 +2112,9 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { if !checkerConfigured { _, _, checkerConfigured = resolveGuardrailsCheckerModel(cfg) } - checkerRefusal(cfg, checkerConfigured) + if err := checkerRefusal(cfg, checkerConfigured); err != nil { + return nil, err + } cfg = resolveAskReviewerDefault(cfg) narratePermissionMode(cfg, checkerConfigured) // Emit the build-once composition facts (token counter / compaction strategy / @@ -2598,6 +2600,9 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // ProjectTrusted: the effective trust fold for the launch workspace (flag, // declared, remembered, or the interactive posture floor), CHROME ONLY. ProjectTrusted: &cfg.TrustProject, + // SubagentAskReviewer: the reviewer state from the same reviewerStatus the + // startup line narrates, so the echo and the diagnostics cannot drift. + SubagentAskReviewer: subagentAskReviewerCapability(cfg), // DeploymentID: the operator-set, opaque deployment label surfaced on // GetCompatibilityInfo. It is passed through VERBATIM and is never // derived here from hostname, pod name, or environment — an inferred label @@ -4259,7 +4264,7 @@ func escapePolicyForConfig(cfg Config, reg *providerRegistry, provider port.LLMP // host paths and could relax the inner decision on that false basis. return inner } - return newEscapePolicy(inner, cfg.Posture, + return newEscapePolicy(inner, withEscapeGuardrailRoute(buildGuardrailsEscapeChecker(cfg, reg, provider))) } @@ -9142,24 +9147,26 @@ const ( // no path to trust, which is false. // The "Three SEPARATE safety axes" substring is a stable test key. selfKnowledgePostureAxes = "Three SEPARATE safety axes, never conflated. (1) SESSION PERMISSION MODE: " + - "exactly three, one per session, in your as `permission-mode`. `default` resolves each call " + + "exactly five, one per session, in your as `permission-mode`. `default` resolves each call " + "deny→ask→allow; `plan` denies mutations and expects a plan presented for approval; `acceptEdits` " + "(accept-edits in mecatui) auto-allows Edit and Write only, leaving Shell and every other mutating " + - "tool on the normal rules. mecatui shows the mode in its header, takes a starting mode at launch, and " + - "cycles default → plan → accept-edits on shift+tab. (2) OPERATOR POSTURE: deployment-wide and fixed " + - "at startup, rising strict < trusted < auto < yolo. The operator sets both with one --permission-mode " + - "token (plan, default, accept-edits, trusted, trusted-accept-edits, auto, yolo): its posture half " + - "is process-wide, its mode half is only the default a new session starts in, and cycling the session " + - "mode never changes the posture. auto and yolo widen what a call is authorized " + - "to do, not only how much runs without asking: both set an allow-all rule for every tool call. " + - "Posture raises project trust on INTERACTIVE roots only: a HEADLESS deployment does NOT trust the " + + "tool on the normal rules; `auto` and `yolo` widen what a call is authorized to do, not only how " + + "much runs without asking: both set an allow-all rule for every tool call. `auto` requires an " + + "enforcing guardrails checker; `yolo` runs without a preventive checker. The operator's " + + "--permission-mode token (plan, default, accept-edits, auto, yolo) sets the mode new sessions start " + + "in and the most permissive mode a session may switch to; switching applies the chosen mode's full " + + "behaviour, so leaving yolo for default restores ordinary approvals. mecatui shows the mode in its " + + "header, takes --permission-mode at launch, and cycles the modes on shift+tab. (2) WORKSPACE TRUST: " + + "a separate yes/no decision about whether the workspace's project instructions and configuration " + + "are adopted; an untrusted workspace can still be read and searched as data. An explicit " + + "--trust-project flag, a declared trusted workspace, or remembered trust grant it on any root. A " + + "--permission-mode token never grants trust; only the deprecated --posture ladder (strict < trusted " + + "< auto < yolo) still raises it, on INTERACTIVE roots only: a HEADLESS deployment does NOT trust the " + "checkout by posture alone. Project ingestion and the read-only child shell follow from project " + - "trust however it was granted — an explicit --trust-project flag, a declared trusted workspace, or " + - "remembered trust grant it on any root, while posture alone grants it only on an interactive one. " + - "(3) GUARDRAILS: an optional model-backed checker over selected " + - "tool arguments and results, independent of permissions and inert until an operator configures a " + - "checker model. Under every mode and posture a matching deny wins and a configured ask is never " + - "suppressed." + "trust. (3) GUARDRAILS: an optional model-backed checker over selected tool arguments and results, " + + "independent of permissions and inert until an operator configures a checker model; it enforces in " + + "every mode except yolo, where it is advisory. Under every mode a matching deny wins and a configured " + + "ask is never suppressed." // selfKnowledgePostureMap is the doc-tree shape, so a lookup lands on the right // page instead of the site root. Every path here is pinned by the drift gate. diff --git a/internal/app/contextual_guardrail_usage_test.go b/internal/app/contextual_guardrail_usage_test.go index 30c257ee51..afe5fa5ceb 100644 --- a/internal/app/contextual_guardrail_usage_test.go +++ b/internal/app/contextual_guardrail_usage_test.go @@ -247,7 +247,7 @@ func TestContextualGuardrailUsage_Scenario2_PathEscapeUsageProductionFlow(t *tes catalog.MustRegister(productionPathUsageTool{}) call := session.NewToolCall("escape", "Read", []byte(`{"path":"`+fixture.target+`"}`)) engine := agent.NewEngine(agent.Deps{LLM: mockllm.New(mockllm.ToolCallTurn(call), mockllm.TextTurn("done")), Catalog: catalog, Policy: policy}) - sess := session.New("path-usage", session.ModeDefault, env.Ref(), session.Limits{}, time.Now()) + sess := session.New("path-usage", session.ModeAuto, env.Ref(), session.Limits{}, time.Now()) for range engine.Run(t.Context(), sess, env, agent.RunRequest{Text: "read outside"}).Events() { } bucket := sess.TokenUsageSnapshot()[session.UsageKindGuardrail] @@ -281,7 +281,7 @@ func TestContextualGuardrailUsage_Scenario2_PathEscapeRetryAndRepeatedChecksPers t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(t.Context(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatal(err) } @@ -331,7 +331,7 @@ func TestContextualGuardrailUsage_Scenario2_PathEscapeTerminalFailurePersistsPar t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(t.Context(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatal(err) } @@ -391,7 +391,7 @@ func TestContextualGuardrailUsage_Scenario2_PathEscapeReevaluationAfterAwaiting( if err != nil { t.Fatal(err) } - sess, err := built1.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + sess, err := built1.Service.CreateSession(t.Context(), session.ModeAuto, session.Limits{}) if err != nil { built1.Close() t.Fatal(err) @@ -483,7 +483,7 @@ func TestContextualGuardrailUsage_Scenario2_ComposedChildNeverArmsPathEscape(t * t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(t.Context(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatal(err) } @@ -589,10 +589,10 @@ func TestEscapePolicyPreservesInnerAndCheckerUsage(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { inner := usagePermissionPolicy{port.PermissionResult{Decision: tc.inner, Usage: pathCheckerUsage(2)}} - policy := newEscapePolicy(inner, PostureAuto, withEscapeGuardrailRoute(pathUsageChecker{ + policy := newEscapePolicy(inner, withEscapeGuardrailRoute(pathUsageChecker{ result: modelhook.CheckResult{Verdict: tc.verdict, Usage: pathCheckerUsage(3)}, err: tc.err, })) - got := policy.Evaluate(t.Context(), "s1", session.ModeDefault, call, ws) + got := policy.Evaluate(t.Context(), "s1", session.ModeAuto, call, ws) if got.Decision.Effect != tc.want || got.Usage.Buckets[session.UsageKindGuardrail].Total.InputTokens != tc.usage { t.Fatalf("result = %+v; want effect %s and usage %d", got, tc.want, tc.usage) } diff --git a/internal/app/escapeclassifier_test.go b/internal/app/escapeclassifier_test.go index 564839f848..18de8cc3fa 100644 --- a/internal/app/escapeclassifier_test.go +++ b/internal/app/escapeclassifier_test.go @@ -248,11 +248,11 @@ func TestPathEscapePosture_Scenario1_PseudoFsClassification(t *testing.T) { t.Errorf("%s(%q) classifies %v, want escapePseudoFS", toolName, path, got) } call := session.NewToolCall("pseudo", toolName, args) - for _, posture := range []Posture{PostureStrict, PostureTrusted, PostureAuto, PostureYolo} { - policy := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), posture) - decision := policy.Evaluate(t.Context(), "s1", session.ModeDefault, call, ws) + policy := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil)) + for _, mode := range []session.PermissionMode{session.ModePlan, session.ModeDefault, session.ModeAccept, session.ModeAuto, session.ModeYolo} { + decision := policy.Evaluate(t.Context(), "s1", mode, call, ws) if decision.Decision.Effect != governance.Deny || !strings.Contains(decision.Decision.Reason, "pseudo-filesystem") { - t.Errorf("%s %s(%q): %+v, want pseudo-fs policy deny", posture, toolName, path, decision) + t.Errorf("%s %s(%q): %+v, want pseudo-fs policy deny", mode, toolName, path, decision) } } if toolName != "ListDir" { @@ -261,7 +261,7 @@ func TestPathEscapePosture_Scenario1_PseudoFsClassification(t *testing.T) { // A configured ask returns before the policy's pseudo-fs check. // Even when approved, the serving workspace must refuse it itself. inner := permpolicy.NewPolicy([]governance.Rule{{Scope: governance.ScopeUser, Tool: "ListDir", Effect: governance.Ask}}, nil) - decision := newEscapePolicy(inner, PostureYolo).Evaluate(t.Context(), "s1", session.ModeDefault, call, ws) + decision := newEscapePolicy(inner).Evaluate(t.Context(), "s1", session.ModeYolo, call, ws) if decision.Decision.Effect != governance.Ask || decision.Decision.AskProvenance != governance.AskProvenanceConfigured { t.Fatalf("configured ask for %q = %+v", path, decision) } diff --git a/internal/app/escapepolicy.go b/internal/app/escapepolicy.go index 18028576f6..9c7f2e93c4 100644 --- a/internal/app/escapepolicy.go +++ b/internal/app/escapepolicy.go @@ -19,11 +19,11 @@ import ( "github.com/stacklok/mecatl/internal/adapter/osfs" ) -// escapepolicy.go is the path-escape-posture decision half: a root-aware +// escapepolicy.go is the path-escape decision half: a root-aware // wrapping port.PermissionPolicy that relaxes an out-of-root Read/ListDir -// escape at the yolo/auto operator postures, an out-of-root WRITE escape at -// yolo (Allow) / auto (Ask), and resolves a strict/trusted out-of-root read OR -// write escape to ASK (instead of a +// escape in yolo/auto SESSION modes, an out-of-root WRITE escape in yolo +// (Allow) / auto (Ask), and resolves an out-of-root read OR write escape in +// every other mode to ASK (instead of a // hard ErrPathEscape dead-end that only pushes the model to an opaque Shell // `cat /path`). It is COMPOSITION, not domain — the escape decision is a // posture/policy concern, and the osfs containment vetting is never stripped @@ -36,8 +36,8 @@ import ( // Ask) into an escape Allow/Ask. The plan-mode hard-deny inside permpolicy's // EvaluateWith therefore runs BEFORE any escape decision (AC4.4). -// escapePolicy wraps an inner port.PermissionPolicy with the posture-derived -// out-of-root read-escape decision, keyed to the session workspace root on +// escapePolicy wraps an inner port.PermissionPolicy with the mode-derived +// out-of-root escape decision, keyed to the session workspace root on // EVERY Evaluate (via the ws the loop hands it). It is a permpolicy sibling: // it implements the SAME port.PermissionPolicy seam, delegating the ordinary // deny/ask/allow fold to the inner policy and layering ONLY the escape @@ -50,12 +50,11 @@ import ( // first call for that root. Learn is forwarded so an "allow always" verdict // on a non-escape call still records against the inner store. type escapePolicy struct { - inner port.PermissionPolicy - posture Posture + inner port.PermissionPolicy - // route is the guardrail-routed escape checker: non-nil ONLY at - // posture auto WITH the operator-tier escape knob configured. nil is the - // byte-identical no-route posture (the ordinary posture table). + // route is the guardrail-routed escape checker: non-nil only WITH the + // operator-tier escape knob configured, and consulted only for calls in an + // auto-mode session. nil is the ordinary mode table. route *escapeGuardrailRoute mu sync.Mutex @@ -66,28 +65,26 @@ type escapePolicy struct { // optional wiring (today: the guardrail-routed escape check). type escapePolicyOption func(*escapePolicy) -// withEscapeGuardrailRoute arms the guardrail-routed escape checker. -// It is a NO-OP unless the posture is auto AND the checker is non-nil — the -// route is the auto-only knob (yolo demotes guardrails to advisory -// and never spends a checker call; strict/trusted keep their own -// Scenario-4 escape Ask). +// withEscapeGuardrailRoute arms the guardrail-routed escape checker. It is a +// no-op for a nil checker. Evaluate consults it only in auto-mode sessions: +// yolo demotes guardrails to advisory and never spends a checker call, and the +// ordinary modes keep their own Scenario-4 escape Ask. func withEscapeGuardrailRoute(checker modelhook.VerdictChecker) escapePolicyOption { return func(p *escapePolicy) { - if p.posture != PostureAuto || checker == nil { + if checker == nil { return } p.route = &escapeGuardrailRoute{checker: checker} } } -// newEscapePolicy builds the shared-engine wrapper. It is active at EVERY -// posture (the caller installs it uniformly): at strict/trusted it converts a -// non-denied escape into the Scenario-4 escape Ask. -func newEscapePolicy(inner port.PermissionPolicy, posture Posture, opts ...escapePolicyOption) port.PermissionPolicy { +// newEscapePolicy builds the shared-engine wrapper. It is active in EVERY +// session mode and decides from the mode Evaluate receives, never from the +// process posture, so a session switched out of yolo regains the escape Ask. +func newEscapePolicy(inner port.PermissionPolicy, opts ...escapePolicyOption) port.PermissionPolicy { p := &escapePolicy{ - inner: inner, - posture: posture, - clfs: make(map[string]*escapeClassifier), + inner: inner, + clfs: make(map[string]*escapeClassifier), } for _, o := range opts { o(p) @@ -126,19 +123,18 @@ func (p *escapePolicy) classifierFor(ws tool.WorkspaceReader) *escapeClassifier // 1. inner Deny → returned verbatim (deny-dominance: a configured deny, the // plan-mode hard-deny, or any inner deny is never relaxed); // 2. inner Ask with ConfiguredAsk → returned verbatim (the configured-Ask -// floor: a CONFIGURED ask on the tool is never suppressed by the posture +// floor: a CONFIGURED ask on the tool is never suppressed by the mode // relax — it demands a human, exactly as the bash substitution floor's // configured-Ask-never-suppressed invariant requires); -// 3. pseudo-fs (/proc, /sys, /dev) → Deny at EVERY posture (the never-relaxed +// 3. pseudo-fs (/proc, /sys, /dev) → Deny in EVERY mode and posture (the never-relaxed // category — an in-process Read of /proc/self/environ would return the // SERVER's raw, unscrubbed environment, a channel the envscrub-scrubbed // Shell parity path does not provide); -// 4. an out-of-root Read/ListDir escape at auto/yolo → Allow (Shell parity); at -// strict/trusted → Ask (Scenario 4 — the legible FS-tool ask instead of -// the ErrPathEscape dead-end); -// 5. an out-of-root WRITE escape → Allow at yolo, Ask at auto AND at -// strict/trusted (Scenarios 3+4 — never a silent un-asked mutation below -// yolo); +// 4. an out-of-root Read/ListDir escape in an auto/yolo session → Allow (Shell +// parity); in any other mode → Ask (Scenario 4 — the legible FS-tool ask +// instead of the ErrPathEscape dead-end); +// 5. an out-of-root WRITE escape → Allow in yolo, Ask in auto AND every other +// mode (Scenarios 3+4 — never a silent un-asked mutation below yolo); // 6. everything else → the inner decision verbatim. func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID, mode session.PermissionMode, c session.ToolCall, ws tool.WorkspaceReader) port.PermissionResult { decision := p.inner.Evaluate(ctx, sessionID, mode, c, ws) @@ -155,7 +151,7 @@ func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID kind := clf.classify(c.Name, c.Args) switch kind { case escapePseudoFS: - // Never-relaxed at every posture: an FS read of a pseudo-fs path would + // Never-relaxed in every mode: an FS read of a pseudo-fs path would // exfiltrate the SERVER's raw environment, a channel Shell does not // provide (the env-scrub gotcha). Hard-deny even at yolo. decision.Decision = governance.PermissionDecision{ @@ -165,10 +161,10 @@ func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID return decision case escapeEscape: // Auto + the operator-tier escape knob only: route the - // escape through the guardrail checker BEFORE the posture row. An + // escape through the guardrail checker BEFORE the mode row. An // unsafe verdict vetoes (Deny); a checker ERROR fails CLOSED to the // write-escape Ask; a safe verdict falls through to the ordinary row. - if p.route != nil { + if p.route != nil && mode == session.ModeAuto { result, err := p.route.review(ctx, c) decision.Usage = decision.Usage.Merge(result.Usage) if err != nil { @@ -179,12 +175,12 @@ func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID decision.Decision = p.route.denyDecision(result.Verdict) return decision } - // safe: fall through to the posture row below. + // safe: fall through to the mode row below. } path := escapePath(c.Args) switch c.Name { case "Read", listDirToolName: - if p.posture >= PostureAuto { + if mode == session.ModeAuto || mode == session.ModeYolo { // Shell parity: at auto/yolo Shell already reads the same bytes, so // the FS read boundary was cosmetic. The relaxed workspace serves // the read; the wrapper only has to not stand in its way. @@ -216,14 +212,14 @@ func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID // configured Ask both returned above (deny-dominance + the // configured-Ask floor), so the relax only ever replaces an inner // ALLOW or an unconfigured floor Ask — never a configured one. - if p.posture >= PostureYolo { + if mode == session.ModeYolo { decision.Decision = governance.PermissionDecision{Effect: governance.Allow} return decision } - if p.posture >= PostureAuto { + if mode == session.ModeAuto { decision.Decision = governance.PermissionDecision{ Effect: governance.Ask, - Reason: "out-of-workspace write: the path escapes the session workspace root (posture auto allows reads but never writes silently)", + Reason: "out-of-workspace write: the path escapes the session workspace root (auto mode allows reads but never writes silently)", } return decision } @@ -240,17 +236,17 @@ func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID // --- the guardrail-routed escape checker (auto + knob only) --- // escapeGuardrailRoute is the composition-level escape PRE-CHECK: an -// out-of-root escape at posture auto, when the operator-tier escape knob is -// configured, is judged by the LLM guardrail checker BEFORE the posture row +// out-of-root escape in an auto-mode session, when the operator-tier escape knob is +// configured, is judged by the LLM guardrail checker BEFORE the mode row // decides. It reuses the SAME engine-backed modelhook.VerdictChecker // (agent.RunGuardrailCheck + ParseVerdict over a tool-less one-turn checker // engine) the modelhook hook-path runner uses — the dual-LLM quarantine, the // whole-output-single-object verdict parse, and the bounded checker engine // are all inherited, not re-implemented. The route is: // -// - auto-only (withEscapeGuardrailRoute refuses to arm it at any other -// posture — yolo demotes guardrails to advisory and never -// spends a checker call; strict/trusted keep their own Scenario-4 Ask); +// - auto-only (Evaluate consults it only for an auto-mode session — yolo +// demotes guardrails to advisory and never spends a checker call; the +// ordinary modes keep their own Scenario-4 Ask); // - main-engine-only (it rides ONLY the main escape policy; a child engine // never relaxes escapes at all — Scenario 5 — so there is no child route); // - deny-dominant (the inner policy fold runs FIRST — a configured Deny or @@ -260,7 +256,7 @@ func (p *escapePolicy) Evaluate(ctx context.Context, sessionID session.SessionID // headless — never to a silent allow and never to a plain pass-through of // the read-allow row). // -// Verdict mapping: safe → fall through to the ordinary auto posture row +// Verdict mapping: safe → fall through to the ordinary auto mode row // (read Allow / write Ask); unsafe → DENY the escape (a checker block is a // veto, mirroring the hook-path PreToolUse block). The content under review // is the call's RAW args JSON, fenced with governance.UntrustedFence and @@ -328,10 +324,10 @@ func escapePath(args json.RawMessage) string { // Learn forwards rule-learning to the inner policy (an "allow always" verdict // on an ordinary call still records against the inner learned-rule store) — // EXCEPT for an out-of-root escape call, which it NEVER forwards: the escape -// relax is posture-derived, not learned, and v1 escape asks are allow-once +// relax is mode-derived, not learned, and v1 escape asks are allow-once // only (a learned out-of-root Write/Edit rule would silently pre-approve // every later write to that path in the session, bypassing the escape Ask the -// posture table promises). Without a session workspace here the call is +// mode table promises). Without a session workspace here the call is // classified against ANY root the policy has already classified for — a call // that escapes under every known root is suppressed; anything else is left to // the inner policy's own LearnableRule discipline. diff --git a/internal/app/guardrails.go b/internal/app/guardrails.go index 31b32ee1d3..3c7ac85ddd 100644 --- a/internal/app/guardrails.go +++ b/internal/app/guardrails.go @@ -699,7 +699,7 @@ func buildGuardrailsChecker(cfg Config, provReg *providerRegistry, provider port } // buildGuardrailsEscapeChecker builds the guardrail-routed permission escape check. -// It is armed only on the main session at posture auto with the escape knob +// It rides only the main session, applies only to auto-mode sessions, and needs the escape knob // and guardrails configured. Generic HookRunner requests carry no usage reporter. func buildGuardrailsEscapeChecker(cfg Config, provReg *providerRegistry, provider port.LLMProvider) modelhook.VerdictChecker { if !cfg.GuardrailsEscape || !guardrailsConfigured(cfg) { diff --git a/internal/app/listdir_external_posture_test.go b/internal/app/listdir_external_posture_test.go index 2d1c665658..b779e06840 100644 --- a/internal/app/listdir_external_posture_test.go +++ b/internal/app/listdir_external_posture_test.go @@ -77,7 +77,7 @@ func TestListDirExternalAbsolutePathFollowsMainPosture(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), postureSessionMode(tc.posture), session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -119,7 +119,7 @@ func TestListDirExternalConfiguredRulesSurviveYolo(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { inner := permpolicy.NewPolicy([]governance.Rule{{Scope: governance.ScopeUser, Tool: "ListDir", Effect: tc.effect}}, nil) - decision := newEscapePolicy(inner, PostureYolo).Evaluate(context.Background(), "s1", session.ModeDefault, call, ws) + decision := newEscapePolicy(inner).Evaluate(context.Background(), "s1", session.ModeYolo, call, ws) if decision.Decision.Effect != tc.effect { t.Fatalf("configured %s became %s at yolo", tc.effect, decision.Decision.Effect) } @@ -187,7 +187,7 @@ func TestListDirPseudoFSAliasApprovedAskStillRefused(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(t.Context(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(t.Context(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatal(err) } @@ -216,7 +216,7 @@ func TestListDirExternalAuthorityDenialStillWins(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/microvm_harness_context_test.go b/internal/app/microvm_harness_context_test.go index 65a5863e26..006b56a1c5 100644 --- a/internal/app/microvm_harness_context_test.go +++ b/internal/app/microvm_harness_context_test.go @@ -569,8 +569,8 @@ func TestMicroVMRepositorySelectionDoesNotGrantProjectAdmission(t *testing.T) { daemon := startPlacementTestDaemon(t) cfg := microVMHarnessConfig(t, daemon, "repository") cfg.TrustProject = false - cfg.Posture, cfg.PostureFlagSet, cfg.GuardrailsDisabled = PostureAuto, true, true - built, err := buildIsolated(t, t.Context(), cfg) + cfg.Posture, cfg.PostureFlagSet = PostureAuto, true + built, err := buildIsolated(t, t.Context(), withInertEnforcingChecker(cfg)) if err != nil { t.Fatal(err) } diff --git a/internal/app/pathescape_guardrail_test.go b/internal/app/pathescape_guardrail_test.go index a5e06b2a01..7cbabe77c1 100644 --- a/internal/app/pathescape_guardrail_test.go +++ b/internal/app/pathescape_guardrail_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "strings" + "sync/atomic" "testing" "github.com/stacklok/mecatl/engine/adapter/mockllm" @@ -11,9 +12,19 @@ import ( "github.com/stacklok/mecatl/engine/governance" "github.com/stacklok/mecatl/engine/port" "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/modelhook" "github.com/stacklok/mecatl/internal/adapter/osfs" ) +// countingVerdictChecker counts Check calls and answers unsafe, so a consulted +// checker would also flip the escape decision to Deny. +type countingVerdictChecker struct{ calls atomic.Int32 } + +func (c *countingVerdictChecker) Check(context.Context, modelhook.CheckRequest) (modelhook.CheckResult, error) { + c.calls.Add(1) + return modelhook.CheckResult{Verdict: modelhook.Verdict{Safe: new(false), Reason: "must not be consulted"}}, nil +} + // pathescape_guardrail_test.go pins guardrail-routed escape checking: at // posture auto WITH the operator-tier // escape knob (guardrails.escape) configured, an out-of-root escape is routed @@ -35,18 +46,24 @@ func buildRoutedEscapePolicy(t *testing.T, cfg Config, checkerTurns ...mockllm.T if checker == nil { t.Fatal("buildGuardrailsChecker returned nil — the test scripts the checker via the same mockllm path the composition uses") } - return newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), PostureAuto, withEscapeGuardrailRoute(checker)) + return newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), withEscapeGuardrailRoute(checker)) } -// evalEscapeAtAuto evaluates one call through the routed policy against a -// real osfs workspace rooted at the fixture workspace. +// evalEscapeAtAuto evaluates one call in an auto-mode session through the +// routed policy against a real osfs workspace rooted at the fixture workspace. func evalEscapeAtAuto(t *testing.T, p port.PermissionPolicy, workspace string, c session.ToolCall) governance.PermissionDecision { + t.Helper() + return evalEscapeInMode(t, p, workspace, session.ModeAuto, c) +} + +// evalEscapeInMode evaluates one call in a session of the given mode. +func evalEscapeInMode(t *testing.T, p port.PermissionPolicy, workspace string, mode session.PermissionMode, c session.ToolCall) governance.PermissionDecision { t.Helper() ws, err := osfs.NewWorkspace(workspace) if err != nil { t.Fatalf("NewWorkspace: %v", err) } - return p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, c, ws).Decision + return p.Evaluate(context.Background(), session.SessionID("s1"), mode, c, ws).Decision } // TestPathEscapePosture_GuardrailRoutedEscape pins AC-W2-G2: auto + the @@ -106,31 +123,26 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { } }) - t.Run("yolo and strict never route", func(t *testing.T) { + t.Run("non-auto session modes never consult the armed route", func(t *testing.T) { t.Parallel() - // The route is the AUTO-only knob: yolo demotes guardrails to advisory - // and never spends a checker call on a decision the posture - // already made; strict/trusted keep their own Scenario-4 escape Ask. - for _, posture := range []Posture{PostureYolo, PostureStrict, PostureTrusted} { - posture := posture - t.Run(posture.String(), func(t *testing.T) { + // The route is armed but consulted only for auto-mode sessions: a yolo + // session demotes guardrails to advisory and never spends a checker + // call; the ordinary modes keep their own Scenario-4 escape Ask. + for _, mode := range []session.PermissionMode{session.ModePlan, session.ModeDefault, session.ModeAccept, session.ModeYolo} { + t.Run(string(mode), func(t *testing.T) { t.Parallel() - // Script a verdict that would DENY if consulted; assert the - // posture row wins and the checker was never consulted (a - // consumed verdict would flip the outcome). - checker := buildGuardrailsChecker(Config{UseMock: true, GuardrailsModel: "checker-model"}, nil, - mockllm.New(mockllm.TextTurn(`{"assessment":"prohibited","concerns":[{"ref":"C1","category":"authority_crossing","rationale":"must not be consulted","source_ref":"call"}],"evidence":[],"missing_evidence":[]}`)), "mock", "m") - p := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), posture, withEscapeGuardrailRoute(checker)) - d := evalEscapeAtAuto(t, p, f.workspace, call) - switch posture { - case PostureYolo: - if d.Effect != governance.Allow { - t.Fatalf("yolo escape = %v, want Allow (the checker must never be consulted at yolo)", d.Effect) - } - default: - if d.Effect != governance.Ask { - t.Fatalf("%s escape = %v, want the Scenario-4 Ask (the route is auto-only)", posture, d.Effect) - } + checker := &countingVerdictChecker{} + p := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), withEscapeGuardrailRoute(checker)) + d := evalEscapeInMode(t, p, f.workspace, mode, call) + want := governance.Ask + if mode == session.ModeYolo { + want = governance.Allow + } + if d.Effect != want { + t.Fatalf("%s-mode escape = %v (%q), want %v", mode, d.Effect, d.Reason, want) + } + if n := checker.calls.Load(); n != 0 { + t.Fatalf("%s-mode escape consulted the checker %d times, want 0 (the route is auto-only)", mode, n) } }) } @@ -140,7 +152,7 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { t.Parallel() // Without the escape knob the auto read row is a plain Allow (Shell // parity) with NO checker call — the route is strictly opt-in. - p := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), PostureAuto) + p := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil)) d := evalEscapeAtAuto(t, p, f.workspace, call) if d.Effect != governance.Allow { t.Fatalf("auto escape without the knob = %v, want Allow (no route, no checker spend)", d.Effect) @@ -153,7 +165,7 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { {Scope: governance.ScopeUser, Tool: "Read", Effect: governance.Deny}, }, nil) checker := buildGuardrailsChecker(cfg, nil, mockllm.New(mockllm.TextTurn(`{"assessment":"acceptable","concerns":[],"evidence":[],"missing_evidence":[]}`)), "mock", "m") - p := newEscapePolicy(inner, PostureAuto, withEscapeGuardrailRoute(checker)) + p := newEscapePolicy(inner, withEscapeGuardrailRoute(checker)) d := evalEscapeAtAuto(t, p, f.workspace, call) if d.Effect != governance.Deny { t.Fatalf("configured deny + routed escape = %v, want Deny — the route runs only after the inner fold", d.Effect) @@ -184,7 +196,7 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -213,7 +225,7 @@ func TestPathEscapePosture_GuardrailRoutedEscape(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/pathescape_scenario2_test.go b/internal/app/pathescape_scenario2_test.go index b5d2d0c09f..47599d49ff 100644 --- a/internal/app/pathescape_scenario2_test.go +++ b/internal/app/pathescape_scenario2_test.go @@ -58,10 +58,11 @@ func setupEscapeFS(t *testing.T) escapeFixture { } // escapeCfg returns the offline Build config for a relaxed-read e2e: mockllm -// provider, real osfs workspace, no network. Posture is set by the caller. +// provider, real osfs workspace, no network. Posture is set by the caller; an +// auto deployment gets an inert enforcing checker (auto requires one). func escapeCfg(t *testing.T, f escapeFixture, posture Posture, turns ...mockllm.Turn) Config { t.Helper() - return Config{ + cfg := Config{ Workspace: f.workspace, NoSoul: true, Posture: posture, @@ -73,6 +74,10 @@ func escapeCfg(t *testing.T, f escapeFixture, posture Posture, turns ...mockllm. return mockllm.New(turns...) }, } + if posture == PostureAuto { + cfg = withInertEnforcingChecker(cfg) + } + return cfg } // auditRecorder is a test ToolCallRecorder capturing each call verbatim. @@ -133,7 +138,7 @@ func TestPathEscapePosture_Scenario2_YoloReadEscapeAllowed(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -163,7 +168,7 @@ func TestPathEscapePosture_Scenario2_AutoReadEscapeAllowed(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -194,7 +199,7 @@ func TestPathEscapePosture_Scenario2_ReadEscapeAuditParity(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -301,7 +306,7 @@ func TestPathEscapePosture_Scenario2_ProcEnvironNotExposed(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -355,7 +360,7 @@ func TestPathEscapePosture_Scenario2_NestedSymlinkEscapeRejected(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -390,7 +395,7 @@ func TestPathEscapePosture_Scenario2_RestartRehydratesRelaxedWorkspace(t *testin if err != nil { t.Fatalf("Build #1: %v", err) } - sess, err := built1.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built1.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { built1.Close() t.Fatalf("CreateSession: %v", err) diff --git a/internal/app/pathescape_scenario3_test.go b/internal/app/pathescape_scenario3_test.go index 4a13d80e21..f0f27942cc 100644 --- a/internal/app/pathescape_scenario3_test.go +++ b/internal/app/pathescape_scenario3_test.go @@ -62,10 +62,10 @@ func setupWriteFS(t *testing.T) writeFixture { } // writeEscapeCfg mirrors escapeCfg but scripts Write turns (posture set by -// the caller). +// the caller; an auto deployment gets an inert enforcing checker). func writeEscapeCfg(t *testing.T, f writeFixture, posture Posture, turns ...mockllm.Turn) Config { t.Helper() - return Config{ + cfg := Config{ Workspace: f.workspace, NoSoul: true, Posture: posture, @@ -77,6 +77,10 @@ func writeEscapeCfg(t *testing.T, f writeFixture, posture Posture, turns ...mock return mockllm.New(turns...) }, } + if posture == PostureAuto { + cfg = withInertEnforcingChecker(cfg) + } + return cfg } // scenario3Call marshals one tool call with the given arg map. @@ -85,10 +89,12 @@ func scenario3Call(id, name string, argMap map[string]string) session.ToolCall { return session.NewToolCall(session.ToolCallID(id), name, json.RawMessage(args)) } -// TestPathEscapePosture_Scenario3_YoloWriteEscapeAllowed pins AC3.1: at -// posture yolo, Write to an out-of-root absolute path creates the file (and a -// second Write replaces it) — the relax flows through the ordinary FS tool, -// never a Shell workaround, and never surfaces an ask at yolo. +// TestPathEscapePosture_Scenario3_YoloWriteEscapeAllowed pins AC3.1: in a +// yolo-mode session, Write to an out-of-root absolute path creates the file +// (and a second Write replaces it) — the relax flows through the ordinary FS +// tool, never a Shell workaround, and never surfaces an ask in yolo. The relax +// keys off the SESSION mode, not the server posture: a default-mode session on +// the same yolo server asks (TestPathEscapePosture_Scenario3_YoloToDefaultTransitionAsks). func TestPathEscapePosture_Scenario3_YoloWriteEscapeAllowed(t *testing.T) { t.Parallel() f := setupWriteFS(t) @@ -103,7 +109,7 @@ func TestPathEscapePosture_Scenario3_YoloWriteEscapeAllowed(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -142,6 +148,156 @@ func TestPathEscapePosture_Scenario3_YoloWriteEscapeAllowed(t *testing.T) { } } +// writeTurnOutcome is what one prompt's run surfaced for the write-escape +// transition tests. +type writeTurnOutcome struct { + asks []session.PendingAsk + results []session.ToolResult +} + +// runWriteTurn drives one prompt, answering every permission ask with verdict. +func runWriteTurn(t *testing.T, built *Built, id session.SessionID, verdict session.ApprovalVerdict) writeTurnOutcome { + t.Helper() + run, err := built.Service.StartRun(context.Background(), id, "write outside the workspace") + if err != nil { + t.Fatalf("StartRun: %v", err) + } + var out writeTurnOutcome + for ev := range run.Events() { + if ev.Type == session.EvPermissionAsk && ev.Ask != nil { + out.asks = append(out.asks, *ev.Ask) + run.Approve(ev.Ask.AskID, verdict) + } + if ev.Type == session.EvToolResult && ev.ToolResult != nil { + out.results = append(out.results, *ev.ToolResult) + } + } + built.Service.FinishRun(id, run) + return out +} + +// TestPathEscapePosture_Scenario3_YoloToDefaultTransitionAsks pins that the +// write-escape relax follows the SESSION mode, not the server posture: on a +// yolo server, a yolo-mode session writes an external file without an ask; +// after SetMode(default) on the SAME session, the next Write to that external +// target raises the escape ask and, denied, leaves the file unchanged. A +// session that starts in default on the yolo server asks the same way, and a +// configured Deny still wins in yolo. +func TestPathEscapePosture_Scenario3_YoloToDefaultTransitionAsks(t *testing.T) { + t.Parallel() + + t.Run("yolo then default on the same session", func(t *testing.T) { + t.Parallel() + f := setupWriteFS(t) + target := filepath.Join(t.TempDir(), "external.txt") + const yoloContent = "written-in-yolo-4d1e" + create := scenario3Call("w1", "Write", map[string]string{"path": target, "content": yoloContent}) + overwrite := scenario3Call("w2", "Write", map[string]string{"path": target, "content": "must-never-land-after-default"}) + built, err := buildIsolated(t, context.Background(), writeEscapeCfg(t, f, PostureYolo, + mockllm.ToolCallTurn(create), + mockllm.TextTurn("done"), + mockllm.ToolCallTurn(overwrite), + mockllm.TextTurn("done"), + )) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + + first := runWriteTurn(t, built, sess.ID, session.VerdictDeny) + if len(first.asks) != 0 { + t.Fatalf("yolo-mode Write escape asked: %+v — yolo must allow it", first.asks) + } + if len(first.results) != 1 || first.results[0].IsError { + t.Fatalf("yolo-mode Write escape results = %+v, want one success", first.results) + } + if data, err := os.ReadFile(target); err != nil || string(data) != yoloContent { + t.Fatalf("after yolo turn: content = %q, err = %v; want %q", data, err, yoloContent) + } + + if _, err := built.Service.SetMode(context.Background(), sess.ID, session.ModeDefault); err != nil { + t.Fatalf("SetMode(default): %v", err) + } + second := runWriteTurn(t, built, sess.ID, session.VerdictDeny) + if len(second.asks) != 1 || second.asks[0].Tool != "Write" || !strings.Contains(second.asks[0].Reason, target) { + t.Fatalf("default-mode Write escape asks = %+v, want one Write escape ask naming %q", second.asks, target) + } + if len(second.results) != 1 || !second.results[0].IsError { + t.Fatalf("denied default-mode Write escape results = %+v, want one error result", second.results) + } + if data, err := os.ReadFile(target); err != nil || string(data) != yoloContent { + t.Fatalf("after denied default turn: content = %q, err = %v; want unchanged %q", data, err, yoloContent) + } + }) + + t.Run("default session on a yolo server asks", func(t *testing.T) { + t.Parallel() + f := setupWriteFS(t) + const original = "external-original-71c0" + if err := os.WriteFile(f.target, []byte(original), 0o644); err != nil { + t.Fatalf("WriteFile(target): %v", err) + } + overwrite := scenario3Call("w1", "Write", map[string]string{"path": f.target, "content": "must-never-land"}) + built, err := buildIsolated(t, context.Background(), writeEscapeCfg(t, f, PostureYolo, + mockllm.ToolCallTurn(overwrite), + mockllm.TextTurn("done"), + )) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + out := runWriteTurn(t, built, sess.ID, session.VerdictDeny) + if len(out.asks) != 1 || out.asks[0].Tool != "Write" { + t.Fatalf("asks = %+v, want one Write escape ask — the yolo server posture must not relax a default-mode session", out.asks) + } + if len(out.results) != 1 || !out.results[0].IsError { + t.Fatalf("results = %+v, want one denied error result", out.results) + } + if data, err := os.ReadFile(f.target); err != nil || string(data) != original { + t.Fatalf("content = %q, err = %v; want unchanged %q", data, err, original) + } + }) + + t.Run("configured deny still denies in yolo", func(t *testing.T) { + t.Parallel() + f := setupWriteFS(t) + settings := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(settings, []byte("permissions:\n deny:\n - Write\n"), 0o600); err != nil { + t.Fatalf("write permission config: %v", err) + } + create := scenario3Call("w1", "Write", map[string]string{"path": f.target, "content": "must-never-land"}) + cfg := writeEscapeCfg(t, f, PostureYolo, mockllm.ToolCallTurn(create), mockllm.TextTurn("done")) + cfg.PermissionConfigs = []string{settings} + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + out := runWriteTurn(t, built, sess.ID, session.VerdictAllowOnce) + if len(out.asks) != 0 { + t.Fatalf("configured deny surfaced asks %+v, want a plain deny", out.asks) + } + if len(out.results) != 1 || !out.results[0].IsError { + t.Fatalf("results = %+v, want one denied error result", out.results) + } + if _, err := os.Stat(f.target); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("Stat(%q) = %v, want nothing written under a configured deny", f.target, err) + } + }) +} + // TestPathEscapePosture_Scenario3_AutoWriteEscapeAsks pins AC3.2: at posture // auto (no guardrail knob), a Write escape surfaces an EvPermissionAsk and // executes ONLY on an allow verdict — a deny verdict leaves nothing written @@ -161,7 +317,7 @@ func TestPathEscapePosture_Scenario3_AutoWriteEscapeAsks(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -203,7 +359,7 @@ func TestPathEscapePosture_Scenario3_AutoWriteEscapeAsks(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeAuto, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -348,7 +504,7 @@ func TestPathEscapePosture_Scenario3_EditLedgerOutOfRoot(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -531,7 +687,7 @@ func TestPathEscapePosture_Scenario3_WriteEscapeMutateSerial(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -610,7 +766,7 @@ func TestPathEscapePosture_Scenario3_WriteEscapeServedThroughOsRoot(t *testing.T t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -649,8 +805,8 @@ func TestPathEscapePosture_Scenario3_ConfiguredDenyWinsOverEscapeAllow(t *testin inner := permpolicy.NewPolicy([]governance.Rule{ {Scope: governance.ScopeUser, Tool: "Write", Effect: governance.Deny}, }, nil) - p := newEscapePolicy(inner, PostureYolo) - d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, call, ws) + p := newEscapePolicy(inner) + d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeYolo, call, ws) if d.Decision.Effect != governance.Deny { t.Fatalf("effect = %v, want Deny — a configured Deny must win over the posture-relaxed escape Allow", d.Decision.Effect) } @@ -661,8 +817,8 @@ func TestPathEscapePosture_Scenario3_ConfiguredDenyWinsOverEscapeAllow(t *testin inner := permpolicy.NewPolicy([]governance.Rule{ {Scope: governance.ScopeUser, Tool: "Write", Effect: governance.Ask}, }, nil) - p := newEscapePolicy(inner, PostureYolo) - d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, call, ws) + p := newEscapePolicy(inner) + d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeYolo, call, ws) if d.Decision.Effect != governance.Ask { t.Fatalf("effect = %v, want Ask — the relax must NEVER suppress a configured Ask", d.Decision.Effect) } @@ -675,11 +831,11 @@ func TestPathEscapePosture_Scenario3_ConfiguredDenyWinsOverEscapeAllow(t *testin t.Parallel() store := permstore.New() inner := permpolicy.NewPolicy(defaultRules(), store) - p := newEscapePolicy(inner, PostureAuto) + p := newEscapePolicy(inner) // Warm the per-root classifier (the Learn guard classifies against the // roots the policy has already seen — in the loop, Learn only ever // follows an Evaluate of the same call). - d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, call, ws) + d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeAuto, call, ws) if d.Decision.Effect != governance.Ask || d.Decision.AskProvenance == governance.AskProvenanceConfigured { t.Fatalf("escape at auto = %+v, want an unconfigured escape Ask", d) } diff --git a/internal/app/pathescape_scenario4_test.go b/internal/app/pathescape_scenario4_test.go index 4fc9deeb5b..a01004ad0d 100644 --- a/internal/app/pathescape_scenario4_test.go +++ b/internal/app/pathescape_scenario4_test.go @@ -303,35 +303,31 @@ func TestPathEscapePosture_Scenario4_PlanModeWriteEscapeDenied(t *testing.T) { writeCall := scenario3Call("w1", "Write", map[string]string{"path": f.target, "content": "x"}) readCall := scenario3Call("r1", "Read", map[string]string{"path": f.target}) - for _, posture := range []Posture{PostureStrict, PostureTrusted} { - posture := posture - t.Run(posture.String(), func(t *testing.T) { - t.Parallel() - p := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil), posture) + p := newEscapePolicy(permpolicy.NewPolicy(defaultRules(), nil)) - d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModePlan, writeCall, ws) - if d.Decision.Effect != governance.Deny { - t.Fatalf("plan-mode write escape at %s = %v, want Deny — the plan-mode hard-deny must precede any escape Ask", posture, d.Decision.Effect) - } + d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModePlan, writeCall, ws) + if d.Decision.Effect != governance.Deny { + t.Fatalf("plan-mode write escape = %v, want Deny — the plan-mode hard-deny must precede any escape Ask", d.Decision.Effect) + } - // Positive control 1: the SAME wrapper, default mode → the escape - // Ask (the deny above is plan-mode precedence, not a blanket - // strict/trusted deny). - d = p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, writeCall, ws) - if d.Decision.Effect != governance.Ask { - t.Fatalf("default-mode write escape at %s = %v, want the escape Ask", posture, d.Decision.Effect) - } - if d.Decision.AskProvenance != governance.AskProvenanceUnknown { - t.Fatalf("escape Ask at %s carries auto-approval provenance %v — it must surface to a human", posture, d.Decision.AskProvenance) - } + // Positive control 1: the SAME wrapper in default and acceptEdits sessions + // → the escape Ask (the deny above is plan-mode precedence, not a blanket + // deny). + for _, mode := range []session.PermissionMode{session.ModeDefault, session.ModeAccept} { + d = p.Evaluate(context.Background(), session.SessionID("s1"), mode, writeCall, ws) + if d.Decision.Effect != governance.Ask { + t.Fatalf("%s-mode write escape = %v, want the escape Ask", mode, d.Decision.Effect) + } + if d.Decision.AskProvenance != governance.AskProvenanceUnknown { + t.Fatalf("%s-mode escape Ask carries auto-approval provenance %v — it must surface to a human", mode, d.Decision.AskProvenance) + } + } - // Positive control 2: a plan-mode READ escape follows the read row - // (allow — plan mode hard-denies mutations only). - d = p.Evaluate(context.Background(), session.SessionID("s1"), session.ModePlan, readCall, ws) - if d.Decision.Effect == governance.Deny { - t.Fatalf("plan-mode read escape at %s = Deny (%q) — plan mode denies mutations only; a read escape must not be hard-denied", posture, d.Decision.Reason) - } - }) + // Positive control 2: a plan-mode READ escape follows the read row + // (allow — plan mode hard-denies mutations only). + d = p.Evaluate(context.Background(), session.SessionID("s1"), session.ModePlan, readCall, ws) + if d.Decision.Effect == governance.Deny { + t.Fatalf("plan-mode read escape = Deny (%q) — plan mode denies mutations only; a read escape must not be hard-denied", d.Decision.Reason) } } @@ -354,7 +350,7 @@ func TestPathEscapePosture_Scenario4_ConfiguredRulesStillWin(t *testing.T) { inner := permpolicy.NewPolicy([]governance.Rule{ {Scope: governance.ScopeUser, Tool: "Read", Effect: governance.Deny}, }, nil) - p := newEscapePolicy(inner, PostureStrict) + p := newEscapePolicy(inner) d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, call, ws) if d.Decision.Effect != governance.Deny { t.Fatalf("effect = %v, want Deny — a configured Deny must win over the escape Ask", d.Decision.Effect) @@ -366,7 +362,7 @@ func TestPathEscapePosture_Scenario4_ConfiguredRulesStillWin(t *testing.T) { inner := permpolicy.NewPolicy([]governance.Rule{ {Scope: governance.ScopeUser, Tool: "Read", Effect: governance.Ask}, }, nil) - p := newEscapePolicy(inner, PostureTrusted) + p := newEscapePolicy(inner) d := p.Evaluate(context.Background(), session.SessionID("s1"), session.ModeDefault, call, ws) if d.Decision.Effect != governance.Ask || d.Decision.AskProvenance != governance.AskProvenanceConfigured { t.Fatalf("effect = %+v, want the CONFIGURED Ask — the escape Ask must never replace a configured Ask", d) diff --git a/internal/app/pathescape_scenario5_test.go b/internal/app/pathescape_scenario5_test.go index 241b929e1f..570873a49f 100644 --- a/internal/app/pathescape_scenario5_test.go +++ b/internal/app/pathescape_scenario5_test.go @@ -88,7 +88,7 @@ func TestPathEscapePosture_Scenario5_ChildReadEscapeDenied(t *testing.T) { t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), postureSessionMode(posture), session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/pathescape_scenario5b_test.go b/internal/app/pathescape_scenario5b_test.go index dd0f7c0002..7a346cf46c 100644 --- a/internal/app/pathescape_scenario5b_test.go +++ b/internal/app/pathescape_scenario5b_test.go @@ -72,7 +72,7 @@ func TestPathEscapePosture_Scenario5_SharedWorkspaceChildNotRelaxed(t *testing.T t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), postureSessionMode(posture), session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } @@ -169,7 +169,7 @@ func TestPathEscapePosture_Scenario5_SharedWorkspaceChildWriteDenied(t *testing. t.Fatalf("Build: %v", err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatalf("CreateSession: %v", err) } diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 75a56bf78d..04cfd5aaf9 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -11,14 +11,12 @@ import ( "github.com/stacklok/mecatl/internal/adapter/permconfig" ) -// permission_mode.go is the COMPOSITION-LAYER named permission-mode vocabulary -//. A token is an operator shorthand that writes an exact pair of -// EXISTING values: the process-wide Posture and the default session -// PermissionMode (server.Config.DefaultMode). It introduces no third source of -// permission state: the table below is the whole mechanism, and it is a lookup, -// not an ordering. Permission relaxation and project trust are independent axes, -// so no total order over the tokens exists and none may be inferred from their -// position in the table. +// permission_mode.go is the COMPOSITION-LAYER named permission-mode vocabulary. +// A token is an operator shorthand that writes EXISTING values: the +// process-wide Posture, the default session PermissionMode +// (server.Config.DefaultMode), and the server ceiling (MaxAllowedMode). The +// table below is the whole mechanism. A token never grants project trust: that +// is a separate decision (--trust-project, trustedWorkspaces, remembered trust). // PermissionModeToken is one named combination of server ceiling and default // session mode. @@ -136,6 +134,19 @@ func foldPermissionMode(cfg Config) (Config, error) { return cfg, nil } +// PostureReplacementToken names the --permission-mode token that replaces a +// deprecated posture value, so every root's deprecation warning names the same +// replacement. trusted maps to default: its trust half is now --trust-project. +func PostureReplacementToken(p Posture) string { + mode, _ := postureToSessionModes(p) + for _, tok := range permissionModeTable { + if tok.SessionMode == mode { + return tok.Name + } + } + return string(session.ModeDefault) +} + // postureToSessionModes maps a Posture to (DefaultSessionMode, MaxAllowedMode) // for the deprecated --posture flag path, maintaining backward compat. func postureToSessionModes(p Posture) (session.PermissionMode, session.PermissionMode) { @@ -149,20 +160,25 @@ func postureToSessionModes(p Posture) (session.PermissionMode, session.Permissio } } -// checkerRefusal WARNs (no longer refuses) when an allow-all mode is configured -// but no guardrails checker is set. In the new architecture the checker -// requirement is enforced at SetMode time (entering ModeAuto requires a checker); -// the startup check is advisory so the operator sees the misconfiguration early. -func checkerRefusal(cfg Config, checkerConfigured bool) { - if cfg.Posture < PostureAuto || checkerConfigured || cfg.GuardrailsDisabled { - return +// checkerRefusal refuses a deployment whose DEFAULT session mode is auto +// without an enforcing checker (missing, --guardrails off, or advisory-only): +// auto's defining guarantee has no default-mode exemption, and unchecked +// autonomy must be chosen explicitly as yolo. A yolo deployment without a +// checker only WARNs that its sessions cannot enter auto. +func checkerRefusal(cfg Config, checkerConfigured bool) error { + if cfg.DefaultSessionMode == session.ModeAuto && !autoCheckerEnforcing(cfg, checkerConfigured) { + state, reason := checkerState(cfg, checkerConfigured) + if state == checkerEnforcing { + state, reason = checkerAdvisory, "configured advisory" + } + return fmt.Errorf("permission mode %q requires an enforcing guardrails checker, but the checker is %s (%s). Fix it by setting a checker with --guardrails-model or binding the guardrail model slot (in enforcing mode), or choose yolo for autonomous operation without a preventive checker", + cfg.resolvedPermissionModeName(), state, reason) } - msg := fmt.Sprintf("permission mode %q: no guardrails checker configured; entering auto mode will be refused at runtime. Fix it by setting a checker with --guardrails-model or binding the guardrail model slot, or run unsupervised with --guardrails off", - cfg.resolvedPermissionModeName()) - if cfg.Posture >= PostureYolo { - msg += ". " + yoloCheckerAdvisoryNote + if cfg.MaxAllowedMode == session.ModeYolo && !autoCheckerEnforcing(cfg, checkerConfigured) { + cfg.diag().Log(context.Background(), port.LevelWarn, + fmt.Sprintf("permission mode %q: no enforcing guardrails checker, so sessions cannot enter auto; configure one with --guardrails-model to allow it", cfg.resolvedPermissionModeName())) } - cfg.diag().Log(context.Background(), port.LevelWarn, msg) + return nil } // yoloCheckerAdvisoryNote states what a configured checker does NOT do at the @@ -248,20 +264,46 @@ func autoCheckerEnforcing(cfg Config, configured bool) bool { return highestSeverityGuardrailMode(specs) != string(modelhook.ModeAdvisory) } -// reviewerState reports the subagent ask reviewer for the startup line. -func reviewerState(cfg Config) string { +// Subagent ask reviewer states: the stable vocabulary of the +// ServerCapabilities.subagent_ask_reviewer echo and the startup line. +const ( + reviewerOn = "on" + reviewerOff = "off" + reviewerInert = "inert" +) + +// reviewerStatus reports the subagent ask reviewer as one stable state plus a +// human-readable reason (empty when there is none). It is the single source +// for both the startup line and the capabilities echo. +func reviewerStatus(cfg Config) (state, reason string) { switch { case cfg.askReviewerDefaultOn: - return "on (default for headless allow-all)" + return reviewerOn, "default for headless allow-all" case cfg.SubagentAskReviewerModel != "" && cfg.Interactive: - return "inert (interactive deployment)" + return reviewerInert, "interactive deployment" case cfg.SubagentAskReviewerModel != "": - return "on (configured)" + return reviewerOn, "configured" case cfg.askReviewerOptOut: - return "off (--subagent-ask-reviewer off)" + return reviewerOff, "--subagent-ask-reviewer off" default: - return "off" + return reviewerOff, "" + } +} + +// subagentAskReviewerCapability is the reviewer state for the capabilities +// echo; the reason stays in diagnostics only. +func subagentAskReviewerCapability(cfg Config) *string { + state, _ := reviewerStatus(cfg) + return &state +} + +// reviewerState reports the subagent ask reviewer for the startup line. +func reviewerState(cfg Config) string { + state, reason := reviewerStatus(cfg) + if reason == "" { + return state } + return state + " (" + reason + ")" } // narratePermissionMode is the ONE build-once line reporting the resolved token, diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index 7d70f938ff..4fc96b0582 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -66,7 +66,12 @@ func TestTokenTableResolvesExactPairs(t *testing.T) { // Through the real Build: the posture echo and the session default. cfg := permissionModeCfg(t, name, port.NopDiagnostics{}) - cfg.GuardrailsDisabled = pair.posture >= PostureAuto + switch pair.posture { + case PostureAuto: + cfg.GuardrailsModel = "mock-checker" + case PostureYolo: + cfg.GuardrailsDisabled = true + } built, err := buildIsolated(t, context.Background(), cfg) if err != nil { t.Fatalf("Build %s: %v", name, err) @@ -118,50 +123,57 @@ func TestTrustedKeepsCurrentMeaning(t *testing.T) { } } -func TestAllowAllTokenRequiresChecker(t *testing.T) { - // The checker gate is now a runtime WARN, not a startup refusal. - // Build succeeds; entering auto mode without a checker is refused at SetMode time. - for _, token := range []string{"auto", "yolo"} { - rec := slogdiagBuffer(t) - cfg := permissionModeCfg(t, token, rec.diag) - built, err := buildIsolated(t, context.Background(), cfg) - if err != nil { - t.Fatalf("%s with no checker must still start (checker gate is now a WARN): %v", token, err) - } - built.Close() - if !strings.Contains(rec.String(), "no guardrails checker") { - t.Errorf("%s without checker must WARN about missing checker; log:\n%s", token, rec.String()) - } - // Either declared choice keeps the WARN from appearing. - off := permissionModeCfg(t, token, port.NopDiagnostics{}) - off.GuardrailsDisabled = true - built2, err := buildIsolated(t, context.Background(), off) - if err != nil { - t.Fatalf("%s with --guardrails off must start: %v", token, err) - } - built2.Close() - checked := permissionModeCfg(t, token, port.NopDiagnostics{}) - checked.GuardrailsModel = "mock-checker" - built3, err := buildIsolated(t, context.Background(), checked) - if err != nil { - t.Fatalf("%s with a configured checker must start: %v", token, err) - } - built3.Close() +func TestAutoTokenRequiresEnforcingChecker(t *testing.T) { + // auto's guarantee is an enforcing checker, with no default-mode exemption: + // every non-enforcing checker state refuses at startup. + for name, mutate := range map[string]func(*Config){ + "missing": func(*Config) {}, + "disabled": func(c *Config) { c.GuardrailsDisabled = true; c.GuardrailsModel = "mock-checker" }, + "advisory-only": func(c *Config) { c.GuardrailsModel = "mock-checker"; c.GuardrailsDefaultMode = "advisory" }, + } { + cfg := permissionModeCfg(t, "auto", port.NopDiagnostics{}) + mutate(&cfg) + if built, err := buildIsolated(t, context.Background(), cfg); err == nil { + built.Close() + t.Fatalf("auto with a %s checker must refuse to start", name) + } else if !strings.Contains(err.Error(), "requires an enforcing guardrails checker") { + t.Fatalf("auto with a %s checker: refusal must name the requirement; got %v", name, err) + } + } + checked := permissionModeCfg(t, "auto", port.NopDiagnostics{}) + checked.GuardrailsModel = "mock-checker" + built, err := buildIsolated(t, context.Background(), checked) + if err != nil { + t.Fatalf("auto with an enforcing checker must start: %v", err) } + built.Close() } -func TestCheckerRefusalNamesEveryFix(t *testing.T) { - // Checker absence is now a startup WARN (not a refusal); the WARN must name every fix. +func TestYoloTokenStartsWithoutChecker(t *testing.T) { + // Unchecked autonomy is yolo: it starts with no checker, WARNing only that + // its sessions cannot enter auto, and refuses an auto session at runtime. rec := slogdiagBuffer(t) - cfg := permissionModeCfg(t, "auto", rec.diag) - built, err := buildIsolated(t, context.Background(), cfg) + built, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "yolo", rec.diag)) if err != nil { - t.Fatalf("auto with no checker must start (WARN only); got error: %v", err) + t.Fatalf("yolo with no checker must start: %v", err) } - built.Close() - for _, want := range []string{"no guardrails checker", "--guardrails-model", "`guardrail` model slot", "--guardrails off"} { - if !strings.Contains(rec.String(), want) { - t.Errorf("checker-absent WARN must name %q; log:\n%s", want, rec.String()) + defer built.Close() + if !strings.Contains(rec.String(), "sessions cannot enter auto") { + t.Errorf("yolo without a checker must WARN that auto is unavailable; log:\n%s", rec.String()) + } + if _, err := built.Service.CreateSession(context.Background(), session.ModeAuto, defaultLimits()); err == nil { + t.Error("yolo without a checker must refuse an auto session") + } +} + +func TestCheckerRefusalNamesEveryFix(t *testing.T) { + _, err := buildIsolated(t, context.Background(), permissionModeCfg(t, "auto", port.NopDiagnostics{})) + if err == nil { + t.Fatal("auto with no checker must refuse to start") + } + for _, want := range []string{"--guardrails-model", "guardrail model slot", "choose yolo"} { + if !strings.Contains(err.Error(), want) { + t.Errorf("refusal must name %q; got: %v", want, err) } } } @@ -312,7 +324,11 @@ func TestHeadlessAllowAllStartsWithoutTrust(t *testing.T) { for _, token := range []string{"auto", "yolo"} { rec := slogdiagBuffer(t) cfg := headlessCfg(t, token, rec.diag) - cfg.GuardrailsDisabled = true + if token == "auto" { + cfg.GuardrailsModel = "mock-checker" + } else { + cfg.GuardrailsDisabled = true + } built, err := buildIsolated(t, context.Background(), cfg) if err != nil { t.Fatalf("%s on a headless root must start: %v", token, err) @@ -351,10 +367,54 @@ func TestInteractiveTrustTokenGrantsTrust(t *testing.T) { } } +// TestPermissionModeTokenDerivesNoTrust pins that the mode surface is not a +// trust decision: an interactive root under any --permission-mode token stays +// untrusted unless an explicit trust source is present, while the deprecated +// --posture surface keeps its interactive trust floor for compatibility. +func TestPermissionModeTokenDerivesNoTrust(t *testing.T) { + trustOf := func(t *testing.T, cfg Config, rec *slogdiagRecorder) bool { + t.Helper() + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + built.Close() + return strings.Contains(rec.lineContaining(`msg="operator posture"`), "trust_project=true") + } + for _, token := range PermissionModeNames() { + t.Run(token, func(t *testing.T) { + withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) + rec := slogdiagBuffer(t) + cfg := permissionModeCfg(t, token, rec.diag) + switch token { + case "auto": + cfg.GuardrailsModel = "mock-checker" + case "yolo": + cfg.GuardrailsDisabled = true + } + if trustOf(t, cfg, rec) { + t.Fatalf("interactive --permission-mode %s granted project trust with no trust source", token) + } + rec = slogdiagBuffer(t) + cfg.Diagnostics = rec.diag + cfg.TrustProject = true + if !trustOf(t, cfg, rec) { + t.Fatalf("--permission-mode %s --trust-project must be trusted", token) + } + }) + } + withTrustEnv(t, trustSettingsEnv(t.TempDir(), nil)) + rec := slogdiagBuffer(t) + legacy := Config{Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, Posture: PostureYolo, PostureFlagSet: true, GuardrailsDisabled: true, Diagnostics: rec.diag} + if !trustOf(t, legacy, rec) { + t.Fatal("deprecated interactive --posture yolo must keep its trust floor") + } +} + func TestAllowAllNarratesSubagentAsymmetry(t *testing.T) { rec := slogdiagBuffer(t) cfg := permissionModeCfg(t, "auto", rec.diag) - cfg.GuardrailsDisabled = true + cfg.GuardrailsModel = "mock-checker" built, err := buildIsolated(t, context.Background(), cfg) if err != nil { t.Fatalf("Build: %v", err) @@ -366,11 +426,11 @@ func TestAllowAllNarratesSubagentAsymmetry(t *testing.T) { } } -// headlessAllowAll is a headless auto deployment with the checker declared off. +// headlessAllowAll is a headless auto deployment with an enforcing checker. func headlessAllowAll(t *testing.T, diag port.Diagnostics) Config { t.Helper() cfg := headlessCfg(t, "auto", diag) - cfg.GuardrailsDisabled = true + cfg.GuardrailsModel = "mock-checker" return cfg } @@ -665,3 +725,11 @@ func TestAuthoritativePostureFoldsPermissionModeKey(t *testing.T) { t.Fatal("a YAML-only permissionMode: yolo must hit the root/no-sandbox refusal fast path") } } + +func TestPostureReplacementToken(t *testing.T) { + for p, want := range map[Posture]string{PostureStrict: "default", PostureTrusted: "default", PostureAuto: "auto", PostureYolo: "yolo"} { + if got := PostureReplacementToken(p); got != want { + t.Errorf("PostureReplacementToken(%s) = %q, want %q", p, got, want) + } + } +} diff --git a/internal/app/posture.go b/internal/app/posture.go index 9cda90d598..bc0468b00c 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -216,7 +216,15 @@ func resolvePosture(cfg Config, ceiling Posture) Posture { // at call time). DefaultSessionMode and MaxAllowedMode are set by foldPermissionMode // (for explicit token/posture flags) or by the backward-compat fallback in Build() // (for the deprecated --yolo alias path). +// +// A posture written by a --permission-mode token or the permissionMode: key +// derives NO trust: workspace trust is a separate decision taken only from +// explicit or remembered trust sources (--trust-project, trustedWorkspaces, +// a remembered grant). Only the deprecated posture surface keeps the floor. func applyPosture(cfg Config) Config { + if cfg.permissionModeName != "" { + return cfg + } switch cfg.Posture { case PostureYolo: // TrustProject floor: INTERACTIVE-only. On a HEADLESS root the ladder does diff --git a/internal/app/posture_build_test.go b/internal/app/posture_build_test.go index 1ae1a72d7c..65e4514071 100644 --- a/internal/app/posture_build_test.go +++ b/internal/app/posture_build_test.go @@ -46,15 +46,14 @@ func postureEchoFromBuild(t *testing.T, built *Built) string { func TestBuildOperatorYAMLPostureSeam(t *testing.T) { t.Run("operator auto flows to composed posture", func(t *testing.T) { diag := slogdiagBuffer(t) - built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, - GuardrailsDisabled: true, - Diagnostics: diag.diag, - }) + built, err := buildIsolated(t, context.Background(), withInertEnforcingChecker(Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, + Diagnostics: diag.diag, + })) if err != nil { t.Fatalf("Build: %v", err) } @@ -76,16 +75,15 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { t.Run("injected user-global posture is discovered", func(t *testing.T) { env := trustSettingsEnv(t.TempDir(), []byte("posture: auto\n")) withTrustEnv(t, env) - built, err := buildIsolated(t, context.Background(), Config{ + built, err := buildIsolated(t, context.Background(), withInertEnforcingChecker(Config{ Workspace: t.TempDir(), Model: "mock", UseMock: true, NoSoul: true, PermissionsConventional: true, permConfigEnv: &env, - GuardrailsDisabled: true, Diagnostics: port.NopDiagnostics{}, - }) + })) if err != nil { t.Fatalf("Build: %v", err) } @@ -99,17 +97,16 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { // narration and the shell consumer must both report the fail-safe result. t.Run("operator auto headless withholds ingestion (fail-safe)", func(t *testing.T) { diag := slogdiagBuffer(t) - built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - Headless: true, - Shell: "/bin/sh", // a configured shell so the UNTRUSTED cause (not the empty-shell cause) is operative for the shell-DISABLED fact - PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, - GuardrailsDisabled: true, - Diagnostics: diag.diag, - }) + built, err := buildIsolated(t, context.Background(), withInertEnforcingChecker(Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: true, + Shell: "/bin/sh", // a configured shell so the UNTRUSTED cause (not the empty-shell cause) is operative for the shell-DISABLED fact + PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, + Diagnostics: diag.diag, + })) if err != nil { t.Fatalf("Build: %v", err) } @@ -143,17 +140,16 @@ func TestBuildOperatorYAMLPostureSeam(t *testing.T) { // both project steering and the read-only child shell. t.Run("operator auto interactive grants ingestion (dev default)", func(t *testing.T) { diag := slogdiagBuffer(t) - built, err := buildIsolated(t, context.Background(), Config{ - Workspace: t.TempDir(), - Model: "mock", - UseMock: true, - NoSoul: true, - Headless: false, - Shell: "/bin/sh", // a configured shell so the untrusted-shell-DISABLED fact would fire if the gate tripped (it must NOT here) - PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, - GuardrailsDisabled: true, - Diagnostics: diag.diag, - }) + built, err := buildIsolated(t, context.Background(), withInertEnforcingChecker(Config{ + Workspace: t.TempDir(), + Model: "mock", + UseMock: true, + NoSoul: true, + Headless: false, + Shell: "/bin/sh", // a configured shell so the untrusted-shell-DISABLED fact would fire if the gate tripped (it must NOT here) + PermissionConfigs: []string{writeOperatorPostureFile(t, "auto")}, + Diagnostics: diag.diag, + })) if err != nil { t.Fatalf("Build: %v", err) } @@ -330,3 +326,43 @@ func TestBuildEchoesProjectTrust(t *testing.T) { }) } } + +// TestBuildEchoesSubagentAskReviewer pins that the capabilities echo carries +// the reviewer state from the same reviewerStatus the startup line narrates. +func TestBuildEchoesSubagentAskReviewer(t *testing.T) { + cases := []struct { + name string + token string + interactive bool + reviewer string + want string + }{ + {"headless default is off", "default", false, "", reviewerOff}, + {"headless yolo defaults on", "yolo", false, "", reviewerOn}, + {"interactive configured is inert", "default", true, "mock", reviewerInert}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if tc.token == "yolo" { + t.Setenv("MECATL_SANDBOX", "1") + } + cfg := permissionModeCfg(t, tc.token, port.NopDiagnostics{}) + cfg.Headless = !tc.interactive + cfg.Interactive = tc.interactive + cfg.SubagentAskReviewerModel = tc.reviewer + cfg.GuardrailsDisabled = tc.token == "yolo" + built, err := buildIsolated(t, context.Background(), cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + caps := built.Service.CompatibilityInfo(context.Background()).GetCapabilities() + if caps.SubagentAskReviewer == nil { + t.Fatal("subagent_ask_reviewer must be set by a composed server") + } + if got := caps.GetSubagentAskReviewer(); got != tc.want { + t.Fatalf("subagent_ask_reviewer = %q, want %q", got, tc.want) + } + }) + } +} diff --git a/internal/app/project_ingestion_build_test.go b/internal/app/project_ingestion_build_test.go index 7b9a1cf69b..b38283365a 100644 --- a/internal/app/project_ingestion_build_test.go +++ b/internal/app/project_ingestion_build_test.go @@ -33,18 +33,17 @@ func TestHeadlessAutoWithoutTrustProjectSuppressesProjectAgentDefs(t *testing.T) ws := seedProjectAgentDef(t, "scout") diag := slogdiagBuffer(t) - built, err := buildIsolated(t, context.Background(), Config{ + built, err := buildIsolated(t, context.Background(), withInertEnforcingChecker(Config{ Workspace: ws, Model: "mock", UseMock: true, NoSoul: true, AgentsConventional: true, Posture: PostureAuto, - GuardrailsDisabled: true, Headless: true, // a headless root does NOT grant ingestion via the ladder // TrustProject stays FALSE — the operator did not pass --trust-project. Diagnostics: diag.diag, - }) + })) if err != nil { t.Fatalf("Build: %v", err) } @@ -63,18 +62,17 @@ func TestHeadlessAutoWithoutTrustProjectSuppressesProjectAgentDefs(t *testing.T) // def — this proves the pinned assertion is non-vacuous. ws := seedProjectAgentDef(t, "scout") - built, err := buildIsolated(t, context.Background(), Config{ + built, err := buildIsolated(t, context.Background(), withInertEnforcingChecker(Config{ Workspace: ws, Model: "mock", UseMock: true, NoSoul: true, AgentsConventional: true, Posture: PostureAuto, - GuardrailsDisabled: true, Headless: true, TrustProject: true, // the explicit opt-in admits ingestion on the headless root Diagnostics: nil, // port.NopDiagnostics via nil - }) + })) if err != nil { t.Fatalf("Build: %v", err) } diff --git a/internal/app/relative_authority_test.go b/internal/app/relative_authority_test.go index 0513394947..0582b44f59 100644 --- a/internal/app/relative_authority_test.go +++ b/internal/app/relative_authority_test.go @@ -36,7 +36,7 @@ forbid(principal, action, resource) when { resource.path like "` + filepath.ToSl t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(ctx, session.ModeYolo, session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/relative_escape_test.go b/internal/app/relative_escape_test.go index bec04e7b89..cab4a96d30 100644 --- a/internal/app/relative_escape_test.go +++ b/internal/app/relative_escape_test.go @@ -41,7 +41,7 @@ func TestYoloRelativeEscapeTools(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatal(err) } @@ -142,7 +142,7 @@ func TestYoloRelativeEscapeConfiguredDeny(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatal(err) } @@ -165,7 +165,7 @@ func TestYoloRelativeEscapeConfiguredAsk(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatal(err) } @@ -226,7 +226,7 @@ func TestYoloRelativeEscapeServiceRefusals(t *testing.T) { t.Fatal(err) } defer built.Close() - sess, err := built.Service.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + sess, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}) if err != nil { t.Fatal(err) } diff --git a/internal/app/remote_execution_test.go b/internal/app/remote_execution_test.go index be450faf20..6329c4b30b 100644 --- a/internal/app/remote_execution_test.go +++ b/internal/app/remote_execution_test.go @@ -236,7 +236,7 @@ func TestRemoteExecutionPreservesOperatorPermissionsUnderAuto(t *testing.T) { session.NewToolCall("allowed", "Shell", json.RawMessage(`{"command":"echo allowed"}`)), session.NewToolCall("project-ask", "Shell", json.RawMessage(`{"command":"echo project-ask"}`)), ), mockllm.TextTurn("done")) - cfg := Config{MockProvider: llm, Workspace: project, Posture: PostureAuto, GuardrailsDisabled: true, PermissionsConventional: true, NoSoul: true, RemoteExecution: true, PlacementScope: "remote", PlacementProvider: remoteFactoryPlacement{env: env}} + cfg := withInertEnforcingChecker(Config{MockProvider: llm, Workspace: project, Posture: PostureAuto, PermissionsConventional: true, NoSoul: true, RemoteExecution: true, PlacementScope: "remote", PlacementProvider: remoteFactoryPlacement{env: env}}) if source == "explicit" { cfg.PermissionConfigs = []string{operatorPath} } diff --git a/internal/app/self_knowledge_posture_test.go b/internal/app/self_knowledge_posture_test.go index 1de8a41b4f..8447b2dd7e 100644 --- a/internal/app/self_knowledge_posture_test.go +++ b/internal/app/self_knowledge_posture_test.go @@ -541,6 +541,21 @@ func TestSelfKnowledgeBehaviouralClaimsMatchImplementation(t *testing.T) { } }) + t.Run("a permission-mode token never grants trust", func(t *testing.T) { + for _, name := range PermissionModeNames() { + tok, err := ParsePermissionMode(name) + if err != nil { + t.Fatal(err) + } + if applyPosture(Config{Posture: tok.Posture, permissionModeName: tok.Name}).TrustProject { + t.Errorf("--permission-mode %s raises TrustProject on an interactive root; the self-knowledge note tells the model a token never grants trust", name) + } + } + if !strings.Contains(selfKnowledgePostureAxes, "--permission-mode token never grants trust") { + t.Error("the axes clause must state that a --permission-mode token never grants workspace trust") + } + }) + t.Run("headless project trust is not limited to --trust-project", func(t *testing.T) { // resolveTrust is the implementation of the claim that a declared or // remembered trust source, not only the --trust-project flag, can grant diff --git a/internal/app/test_helpers_test.go b/internal/app/test_helpers_test.go index 66e0b55167..4a6525dab4 100644 --- a/internal/app/test_helpers_test.go +++ b/internal/app/test_helpers_test.go @@ -7,6 +7,7 @@ import ( "github.com/stacklok/mecatl/engine/adapter/mockllm" "github.com/stacklok/mecatl/engine/learning" + "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/internal/adapter/skillstore" ) @@ -24,6 +25,23 @@ func buildIsolated(t testing.TB, ctx context.Context, cfg Config) (*Built, error return Build(ctx, isolateConfig(t, cfg)) } +// withInertEnforcingChecker declares an enforcing guardrails checker whose +// only rule matches no tool, so an auto deployment is admissible without the +// checker reviewing (or consuming mock turns for) the test's own calls. +func withInertEnforcingChecker(cfg Config) Config { + cfg.GuardrailsDisabled = false + cfg.GuardrailsModel = "mock-checker" + cfg.GuardrailsRules = []GuardrailRule{{Match: "NoSuchTool_inert_checker_rule", Mode: "block"}} + return cfg +} + +// postureSessionMode is the default session mode a deployment at posture p +// creates, so a posture-parameterized test can run its session in that mode. +func postureSessionMode(p Posture) session.PermissionMode { + mode, _ := postureToSessionModes(p) + return mode +} + func TestBuildIsolatedIgnoresAmbientUserModel(t *testing.T) { xdg := t.TempDir() t.Setenv("XDG_CONFIG_HOME", xdg) diff --git a/internal/configgen/build.go b/internal/configgen/build.go index eae827a6ac..e604513c92 100644 --- a/internal/configgen/build.go +++ b/internal/configgen/build.go @@ -403,10 +403,11 @@ func permissionModeSubtree(docs Docs) *Subtree { return &Subtree{ Key: "permissionMode", Tier: TierOperator, - Doc: "OPERATOR-TIER named permission mode: plan, default, accept-edits, trusted, " + - "trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, " + - "fixed at startup, and the mode new sessions start in, which each session may change. auto " + - "and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. " + + Doc: "OPERATOR-TIER named permission mode: plan, default, accept-edits, auto, or yolo. " + + "Each token sets two things: the mode new sessions start in, and the server ceiling, " + + "fixed at startup, which is the most permissive mode a session may switch to " + + "(accept-edits for plan, default, and accept-edits). auto refuses to start without an " + + "enforcing guardrails checker; yolo needs none. A mode never grants workspace trust. " + "An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: " + "key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default.", CommentedOut: true, @@ -416,7 +417,7 @@ func permissionModeSubtree(docs Docs) *Subtree { Type: "string", Default: "(empty)", Doc: docFor(docs, "Config.PermissionMode", "the named permission-mode token"), - ExampleValue: "trusted-accept-edits", + ExampleValue: "accept-edits", }}, } } diff --git a/internal/configgen/settings.skeleton.yaml b/internal/configgen/settings.skeleton.yaml index 4f4ed238e9..eba9a20786 100644 --- a/internal/configgen/settings.skeleton.yaml +++ b/internal/configgen/settings.skeleton.yaml @@ -97,14 +97,14 @@ # failClosed: false #| === permissionMode === (tier: operator) -#| OPERATOR-TIER named permission mode: plan, default, accept-edits, trusted, -#| trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide -#| posture, fixed at startup, and the mode new sessions start in, which each session may -#| change. auto and yolo refuse to start without a guardrails checker unless guardrails -#| are explicitly off. An explicit --permission-mode out-ranks this key, and it -#| out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with -#| a WARN. Empty = keep the CLI/default. -# permissionMode: trusted-accept-edits +#| OPERATOR-TIER named permission mode: plan, default, accept-edits, auto, or yolo. Each +#| token sets two things: the mode new sessions start in, and the server ceiling, fixed +#| at startup, which is the most permissive mode a session may switch to (accept-edits +#| for plan, default, and accept-edits). auto refuses to start without an enforcing +#| guardrails checker; yolo needs none. A mode never grants workspace trust. An explicit +#| --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A +#| project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. +# permissionMode: accept-edits #| === posture === (tier: operator) #| DEPRECATED: use permissionMode: instead; still honoured with a WARN for one release. diff --git a/sdk/typescript/etc/mecatl-sdk-deno.api.md b/sdk/typescript/etc/mecatl-sdk-deno.api.md index fecb875880..e5f055749f 100644 --- a/sdk/typescript/etc/mecatl-sdk-deno.api.md +++ b/sdk/typescript/etc/mecatl-sdk-deno.api.md @@ -1338,6 +1338,7 @@ export interface ServerCapabilities { readonly storageCleanup: boolean; // (undocumented) readonly storageHealth: boolean; + readonly subagentAskReviewer?: string; // (undocumented) readonly teams: boolean; // (undocumented) @@ -1378,6 +1379,7 @@ export const ServerFeature: { readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; + readonly SessionPermissionModes: "session_permission_modes"; readonly SkillFiles: "skill_files"; readonly WatchSessionEvents: "watch_session_events"; }; @@ -1503,6 +1505,8 @@ export const SessionMode: { readonly Default: 1; readonly Plan: 2; readonly AcceptEdits: 3; + readonly Auto: 4; + readonly Yolo: 5; }; // @public diff --git a/sdk/typescript/etc/mecatl-sdk-node.api.md b/sdk/typescript/etc/mecatl-sdk-node.api.md index fbd38d6c81..416378d41d 100644 --- a/sdk/typescript/etc/mecatl-sdk-node.api.md +++ b/sdk/typescript/etc/mecatl-sdk-node.api.md @@ -1367,6 +1367,7 @@ export interface ServerCapabilities { readonly storageCleanup: boolean; // (undocumented) readonly storageHealth: boolean; + readonly subagentAskReviewer?: string; // (undocumented) readonly teams: boolean; // (undocumented) @@ -1407,6 +1408,7 @@ export const ServerFeature: { readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; + readonly SessionPermissionModes: "session_permission_modes"; readonly SkillFiles: "skill_files"; readonly WatchSessionEvents: "watch_session_events"; }; @@ -1532,6 +1534,8 @@ export const SessionMode: { readonly Default: 1; readonly Plan: 2; readonly AcceptEdits: 3; + readonly Auto: 4; + readonly Yolo: 5; }; // @public diff --git a/sdk/typescript/etc/mecatl-sdk.api.md b/sdk/typescript/etc/mecatl-sdk.api.md index 940a9bb01b..e8073cad74 100644 --- a/sdk/typescript/etc/mecatl-sdk.api.md +++ b/sdk/typescript/etc/mecatl-sdk.api.md @@ -1290,6 +1290,7 @@ export interface ServerCapabilities { readonly storageCleanup: boolean; // (undocumented) readonly storageHealth: boolean; + readonly subagentAskReviewer?: string; // (undocumented) readonly teams: boolean; // (undocumented) @@ -1330,6 +1331,7 @@ export const ServerFeature: { readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; + readonly SessionPermissionModes: "session_permission_modes"; readonly SkillFiles: "skill_files"; readonly WatchSessionEvents: "watch_session_events"; }; @@ -1455,6 +1457,8 @@ export const SessionMode: { readonly Default: 1; readonly Plan: 2; readonly AcceptEdits: 3; + readonly Auto: 4; + readonly Yolo: 5; }; // @public diff --git a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts index f2e85bc138..b4c4af3a0e 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("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIpgDChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSMAoJZXhlY3V0aW9uGAwgASgLMh0ubWVjYXRsLnYxLkV4ZWN1dGlvblNlbGVjdGlvbhIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMSHQoVYWdlbnRfZGVmaW5pdGlvbl9uYW1lGA0gASgJSgQIARACSgQICBAJSgQIBhAHUgl3b3Jrc3BhY2VSEXNvdXJjZV9zZXNzaW9uX2lkUgdwcm9maWxlImwKEkV4ZWN1dGlvblNlbGVjdGlvbhImCgRub25lGAEgASgLMhgubWVjYXRsLnYxLkV4ZWN1dGlvbk5vbmUSLgoIdGVtcGxhdGUYAiABKAsyHC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGUiDwoNRXhlY3V0aW9uTm9uZSIxChFFeGVjdXRpb25UZW1wbGF0ZRIKCgJpZBgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCSIfCh1MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdCJtCh5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USLwoFaXRlbXMYASADKAsyIC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGVJbmZvEhoKEmludmVudG9yeV9yZXZpc2lvbhgCIAEoCSK9AgoVRXhlY3V0aW9uVGVtcGxhdGVJbmZvEi4KCHRlbXBsYXRlGAEgASgLMhwubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSFQoNZGlzcGxheV90b2tlbhgEIAEoCRJECgpleHRlbnNpb25zGAUgAygLMjAubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlSW5mby5FeHRlbnNpb25zRW50cnkSIAoYZGVjbGFyZWRfZXhlY3V0aW9uX2ZpbGVzGAYgASgIEh8KF2RlY2xhcmVkX2J1aWx0X2luX3NoZWxsGAcgASgIGjEKD0V4dGVuc2lvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIrEBCg1NY3BTZXJ2ZXJTcGVjEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEgwKBHR5cGUYAyABKAkSDwoHY29tbWFuZBgEIAEoCRI2CgdoZWFkZXJzGAUgAygLMiUubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMuSGVhZGVyc0VudHJ5Gi4KDEhlYWRlcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIisKFEdldFNlcnZlckluZm9SZXF1ZXN0EhMKC3Byb3ZpZGVyX2lkGAEgASgJIm8KFUdldFNlcnZlckluZm9SZXNwb25zZRIQCghidWlsZF9pZBgBIAEoCRIdChVzZXJ2ZXJfaW1wbGVtZW50YXRpb24YAiABKAkSJQodbGxtX3Byb3ZpZGVyX2Rpc3BsYXlfZW5kcG9pbnQYAyABKAkiHQobR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0IowBChxHZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEhEKCWFwaV9tYWpvchgBIAEoBRIzCgxjYXBhYmlsaXRpZXMYAiABKAsyHS5tZWNhdGwudjEuU2VydmVyQ2FwYWJpbGl0aWVzEhAKCGZlYXR1cmVzGAMgAygJEhIKCmRlcGxveW1lbnQYBCABKAki7wUKElNlcnZlckNhcGFiaWxpdGllcxILCgNtY3AYASABKAgSFgoOc2xhc2hfY29tbWFuZHMYAiABKAgSDgoGbWVtb3J5GAMgASgIEg4KBnNraWxscxgEIAEoCBINCgV0ZWFtcxgFIAEoCBINCgVzaGVsbBgGIAEoCBINCgVpbWFnZRgHIAEoCBINCgVhdWRpbxgIIAEoCBIOCgZhZ2VudHMYCSABKAgSDAoEc291bBgKIAEoCBISCgp1c2VyX21vZGVsGAsgASgIEhcKD21vZGVsX3NlbGVjdGlvbhgMIAEoCBIPCgdwb3N0dXJlGA0gASgJEhEKCXdvcmt0cmVlcxgOIAEoCBISCgpzY2hlZHVsaW5nGA8gASgIEhIKCnJlZmxlY3Rpb24YECABKAgSGgoSbGVhcm5pbmdfcHJvcG9zYWxzGBEgASgIEhYKDmxlYXJuZWRfc2tpbGxzGBIgASgIEhcKD3N0b3JhZ2VfY2xlYW51cBgWIAEoCBI4CgxtYW51YWxfZHJlYW0YEyABKAsyIi5tZWNhdGwudjEuTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSFgoOc3RvcmFnZV9oZWFsdGgYFyABKAgSDQoFc3RlZXIYGCABKAgSGQoRbWFudWFsX2NvbXBhY3Rpb24YGSABKAgSFQoNc2Vzc2lvbl9kZWJ1ZxgaIAEoCBIRCglkZWJ1Z19tY3AYGyABKAgSHAoUd29ya3NwYWNlX2Vucm9sbG1lbnQYHCABKAgSHAoUbWNwX2Nvbm5lY3Rvcl9zdGF0dXMYHSABKAgSEwoLbWNwX3JlZnJlc2gYHiABKAgSGwoTZXhlY3V0aW9uX3RlbXBsYXRlcxgfIAEoCBIcCg9wcm9qZWN0X3RydXN0ZWQYICABKAhIAIgBAUISChBfcHJvamVjdF90cnVzdGVkSgQIFBAVSgQIFRAWUg9sZWdhY3lfYWRvcHRpb25SEXN0b3JhZ2VfbWlncmF0aW9uIjUKH0xpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1JlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCSKyAQogTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVzcG9uc2USFAoMYXZhaWxhYmlsaXR5GAEgASgJEhgKEGVucm9sbG1lbnRfc3RhdGUYAiABKAkSMQoKY29ubmVjdG9ycxgDIAMoCzIdLm1lY2F0bC52MS5NY3BDb25uZWN0b3JTdGF0dXMSGAoQdG90YWxfY29ubmVjdG9ycxgEIAEoDRIRCgl0cnVuY2F0ZWQYBSABKAgiTwoSTWNwQ29ubmVjdG9yU3RhdHVzEgwKBG5hbWUYASABKAkSFwoPY2F0YWxvZ3VlX3N0YXRlGAIgASgJEhIKCnRvb2xfY291bnQYAyABKA0iiAIKFUNyZWF0ZVNlc3Npb25SZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEjwKFHNlc3Npb25fY2FwYWJpbGl0aWVzGAMgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25DYXBhYmlsaXRpZXMSMAoOcmVzb2x2ZWRfbW9kZWwYBCABKAsyGC5tZWNhdGwudjEuUmVzb2x2ZWRNb2RlbBIvCglwbGFjZW1lbnQYBSABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGESJgoecmVzb2x2ZWRfYWdlbnRfZGVmaW5pdGlvbl9uYW1lGAYgASgJSgQIAhADUgxjYXBhYmlsaXRpZXMiUgoRUGxhY2VtZW50TWV0YWRhdGESDAoEa2luZBgBIAEoCRINCgVsYWJlbBgCIAEoCRIOCgZicmFuY2gYAyABKAkSEAoIcmV2aXNpb24YBCABKAkiaAoNUmVzb2x2ZWRNb2RlbBITCgtwcm92aWRlcl9pZBgBIAEoCRIQCghtb2RlbF9pZBgCIAEoCRIWCg5jb250ZXh0X3dpbmRvdxgDIAEoAxIYChByZWFzb25pbmdfZWZmb3J0GAQgASgJImQKE1Nlc3Npb25DYXBhYmlsaXRpZXMSDQoFaW1hZ2UYASABKAgSDQoFYXVkaW8YAiABKAgSFwoPZXhlY3V0aW9uX2ZpbGVzGAMgASgIEhYKDmJ1aWx0X2luX3NoZWxsGAQgASgIIjAKEUdldFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiOQoSR2V0U2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiI6ChtHZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJSChRBY3Rpdml0eVJlcGxheVN0YXR1cxIRCglhdmFpbGFibGUYASABKAgSEAoIY29tcGxldGUYAiABKAgSFQoNYXV0aG9yaXRhdGl2ZRgDIAEoCCLtAQocR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEjAKCG1lc3NhZ2VzGAIgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2USEAoIY29tcGxldGUYAyABKAgSMQoIYWN0aXZpdHkYBCABKAsyHy5tZWNhdGwudjEuQWN0aXZpdHlSZXBsYXlTdGF0dXMSDAoEa2luZBgFIAEoCRI0CgxyZWxhdGlvbnNoaXAYBiABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcCI5ChpTdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjcKGFN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIlgKGVdhdGNoU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIOCgZjdXJzb3IYAiABKAkSDgoGcnVuX2lkGAMgASgJIlwKGldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50Eg4KBmN1cnNvchgCIAEoCRINCgVwaGFzZRgDIAEoCSI4ChNMaXN0U2Vzc2lvbnNSZXF1ZXN0EhEKCXBhZ2Vfc2l6ZRgBIAEoBRIOCgZjdXJzb3IYAiABKAkiTgoJUHJpbmNpcGFsEg4KBmlzc3VlchgBIAEoCRIPCgdzdWJqZWN0GAIgASgJEhIKCmdyYW50X3R5cGUYAyABKAkSDAoEbmFtZRgEIAEoCSL+BAoOU2Vzc2lvblN1bW1hcnkSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAIgASgDEg0KBXN0YXRlGAMgASgJEg0KBXR1cm5zGAQgASgFEhAKCG1vZGVsX2lkGAUgASgJEhcKD2NyZWF0ZWRfYXRfdW5peBgGIAEoAxIjCgVvd25lchgIIAEoCzIULm1lY2F0bC52MS5QcmluY2lwYWwSDAoEa2luZBgJIAEoCRI0CgxyZWxhdGlvbnNoaXAYCiABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBI9CgxjYXBhYmlsaXRpZXMYCyABKAsyJy5tZWNhdGwudjEuU2Vzc2lvbkludmVudG9yeUNhcGFiaWxpdGllcxITCgtyZWFzb25fY29kZRgMIAEoCRIvCglwbGFjZW1lbnQYDyABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGESLwoOdGl0bGVfbWV0YWRhdGEYECABKAsyFy5tZWNhdGwudjEuU2Vzc2lvblRpdGxlEj4KC3Rva2VuX3VzYWdlGBEgAygLMikubWVjYXRsLnYxLlNlc3Npb25TdW1tYXJ5LlRva2VuVXNhZ2VFbnRyeRIWCg5hY3Rpdml0eV9zdGF0ZRgSIAEoCRpICg9Ub2tlblVzYWdlRW50cnkSCwoDa2V5GAEgASgJEiQKBXZhbHVlGAIgASgLMhUubWVjYXRsLnYxLlRva2VuVXNhZ2U6AjgBSgQIBxAISgQIDRAOSgQIDhAPUgV0aXRsZVIJd29ya3NwYWNlUhB0aXRsZV9wcm92ZW5hbmNlIuYBChNTZXNzaW9uUmVsYXRpb25zaGlwEhkKEXBhcmVudF9zZXNzaW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSGQoMYnJhbmNoX2luZGV4GAMgASgFSACIAQESFQoNc2NoZWR1bGVfbmFtZRgEIAEoCRIZChFvcmlnaW5fc2Vzc2lvbl9pZBgFIAEoCRIPCgd0ZWFtX2lkGAYgASgJEhMKC21lbWJlcl9uYW1lGAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAggASgJQg8KDV9icmFuY2hfaW5kZXgikgIKHFNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcHVibGljX2NoYXQYASABKAgSDwoHaW5zcGVjdBgCIAEoCBIgChhhdXRob3JpdGF0aXZlX3RyYW5zY3JpcHQYAyABKAgSFwoPYWN0aXZpdHlfcmVwbGF5GAQgASgIEg8KB2NvcHlfaWQYBSABKAgSFwoPdmlld190cmFuc2NyaXB0GAYgASgIEgwKBGZvcmsYByABKAgSDgoGcmVuYW1lGAggASgIEg4KBmRlbGV0ZRgJIAEoCBI5CgdyZWFzb25zGAogASgLMigubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlBY3Rpb25SZWFzb25zIp0BCh1TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucxITCgtwdWJsaWNfY2hhdBgBIAEoCRIPCgdpbnNwZWN0GAIgASgJEg8KB2NvcHlfaWQYAyABKAkSFwoPdmlld190cmFuc2NyaXB0GAQgASgJEgwKBGZvcmsYBSABKAkSDgoGcmVuYW1lGAYgASgJEg4KBmRlbGV0ZRgHIAEoCSJtChRMaXN0U2Vzc2lvbnNSZXNwb25zZRIrCghzZXNzaW9ucxgBIAMoCzIZLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeRITCgtuZXh0X2N1cnNvchgCIAEoCRITCgt0b3RhbF9jb3VudBgDIAEoBSIZChdHZXRTdG9yYWdlSGVhbHRoUmVxdWVzdCLeAQoPUmV0ZW50aW9uUG9saWN5EhwKFG1haW5fbWF4X2FnZV9zZWNvbmRzGAEgASgDEhYKDm1haW5fbWF4X2NvdW50GAIgASgFEh0KFWNoaWxkX21heF9hZ2Vfc2Vjb25kcxgDIAEoAxIXCg9jaGlsZF9tYXhfY291bnQYBCABKAUSIQoZc2NoZWR1bGVkX21heF9hZ2Vfc2Vjb25kcxgFIAEoAxIbChNzY2hlZHVsZWRfbWF4X2NvdW50GAYgASgFEh0KFXN3ZWVwX2NhZGVuY2Vfc2Vjb25kcxgHIAEoAyLJBwoYR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEhEKCWF2YWlsYWJsZRgBIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAiABKAkSFQoNY3VycmVudF9ieXRlcxgDIAEoAxIfChdjdXJyZW50X2J5dGVzX2F2YWlsYWJsZRgEIAEoCBIZChFyZWNsYWltYWJsZV9ieXRlcxgFIAEoAxIjChtyZWNsYWltYWJsZV9ieXRlc19hdmFpbGFibGUYBiABKAgSFQoNc2Vzc2lvbl9jb3VudBgHIAEoAxISCgpmaWxlX2NvdW50GAggASgDEhAKCHYxX2NvdW50GAkgASgDEhAKCHYyX2NvdW50GAogASgDEhIKCm1haW5fY291bnQYCyABKAMSEwoLY2hpbGRfY291bnQYDCABKAMSFwoPc2NoZWR1bGVkX2NvdW50GA0gASgDEhUKDXVua25vd25fY291bnQYDiABKAMSFQoNY29ycnVwdF9jb3VudBgPIAEoAxIqCgZwb2xpY3kYECABKAsyGi5tZWNhdGwudjEuUmV0ZW50aW9uUG9saWN5EhcKD2xhc3Rfc3dlZXBfdW5peBgRIAEoAxIcChRsYXN0X3N3ZWVwX2F2YWlsYWJsZRgSIAEoCBIXCg9uZXh0X3N3ZWVwX3VuaXgYEyABKAMSHAoUbmV4dF9zd2VlcF9hdmFpbGFibGUYFCABKAgSEgoKYWN0aXZlX2pvYhgVIAEoCRIUCgxsYXN0X2ZhaWx1cmUYFiABKAkSJAocb3duZXJsZXNzX3Nlc3Npb25zX2F2YWlsYWJsZRgXIAEoCBItCiVvd25lcmxlc3Nfc2Vzc2lvbnNfdW5hdmFpbGFibGVfcmVhc29uGBggASgJEh8KF293bmVybGVzc19zZXNzaW9uX2NvdW50GBkgASgDEh0KFW93bmVybGVzc19zZXNzaW9uX2lkcxgaIAMoCRInCh9vd25lcmxlc3Nfc2Vzc2lvbl9pZHNfdHJ1bmNhdGVkGBsgASgIEiUKHW93bmVybGVzc19zY2hlZHVsZXNfYXZhaWxhYmxlGBwgASgIEi4KJm93bmVybGVzc19zY2hlZHVsZXNfdW5hdmFpbGFibGVfcmVhc29uGB0gASgJEiAKGG93bmVybGVzc19zY2hlZHVsZV9jb3VudBgeIAEoAxIgChhvd25lcmxlc3Nfc2NoZWR1bGVfbmFtZXMYHyADKAkSKgoib3duZXJsZXNzX3NjaGVkdWxlX25hbWVzX3RydW5jYXRlZBggIAEoCCLZAgoNQ2xlYW51cENvdW50cxINCgV0b3RhbBgBIAEoBRI1CgdieV9raW5kGAIgAygLMiQubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlLaW5kRW50cnkSNwoIYnlfc3RhdGUYAyADKAsyJS5tZWNhdGwudjEuQ2xlYW51cENvdW50cy5CeVN0YXRlRW50cnkSOQoJYnlfcmVhc29uGAQgAygLMiYubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlSZWFzb25FbnRyeRotCgtCeUtpbmRFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAU6AjgBGi4KDEJ5U3RhdGVFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAU6AjgBGi8KDUJ5UmVhc29uRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ASKGAQoQQ2xlYW51cENhbmRpZGF0ZRISCgpzZXNzaW9uX2lkGAEgASgJEgwKBGtpbmQYAiABKAkSDQoFc3RhdGUYAyABKAkSDgoGcmVhc29uGAQgASgJEhgKEG1vZGlmaWVkX2F0X3VuaXgYBSABKAMSFwoPZXN0aW1hdGVkX2J5dGVzGAYgASgDIioKGVBsYW5TZXNzaW9uQ2xlYW51cFJlcXVlc3QSDQoFa2luZHMYASADKAki0wIKGlBsYW5TZXNzaW9uQ2xlYW51cFJlc3BvbnNlEhoKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCRIRCglhdmFpbGFibGUYAiABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAMgASgJEhIKCmdlbmVyYXRpb24YBCABKAkSFgoOcG9saWN5X3ZlcnNpb24YBSABKAkSLQoIZWxpZ2libGUYBiADKAsyGy5tZWNhdGwudjEuQ2xlYW51cENhbmRpZGF0ZRIrCglwcm90ZWN0ZWQYByABKAsyGC5tZWNhdGwudjEuQ2xlYW51cENvdW50cxIXCg9lc3RpbWF0ZWRfYnl0ZXMYCCABKAMSFgoOcGxhbm5lZF9qb2JfaWQYCSABKAkSMQoPZWxpZ2libGVfY291bnRzGAogASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMiQQoaQXBwbHlTZXNzaW9uQ2xlYW51cFJlcXVlc3QSIwoSY29uZmlybWF0aW9uX3Rva2VuGAEgASgJQge6SARyAhABIjYKG0NhbmNlbFNlc3Npb25DbGVhbnVwUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiNgobR2V0U2Vzc2lvbkNsZWFudXBKb2JSZXF1ZXN0EhcKBmpvYl9pZBgBIAEoCUIHukgEcgIQASJNChBDbGVhbnVwSXRlbUVycm9yEhMKC2l0ZW1faGFuZGxlGAEgASgJEhMKC3JlYXNvbl9jb2RlGAIgASgJEg8KB21lc3NhZ2UYAyABKAkirAEKCkNsZWFudXBKb2ISDgoGam9iX2lkGAEgASgJEg0KBXN0YXRlGAIgASgJEhEKCXByb2Nlc3NlZBgDIAEoBRIPCgdkZWxldGVkGAQgASgFEg8KB3NraXBwZWQYBSABKAUSDQoFc3RhbGUYBiABKAUSDgoGZmFpbGVkGAcgASgFEisKBmVycm9ycxgIIAMoCzIbLm1lY2F0bC52MS5DbGVhbnVwSXRlbUVycm9yIlYKDlNldE1vZGVSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESJwoEbW9kZRgCIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZSI2Cg9TZXRNb2RlUmVzcG9uc2USIwoHc2Vzc2lvbhgBIAEoCzISLm1lY2F0bC52MS5TZXNzaW9uIjIKE0Nsb3NlU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASIWChRDbG9zZVNlc3Npb25SZXNwb25zZSJLChRSZW5hbWVTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEhYKBXRpdGxlGAIgASgJQge6SARyAhABIjwKFVJlbmFtZVNlc3Npb25SZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iMwoURGVsZXRlU2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASIXChVEZWxldGVTZXNzaW9uUmVzcG9uc2UibwoTQ2xlYXJTZXNzaW9uUmVxdWVzdBIiChFzb3VyY2Vfc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIeChF3b3JrdHJlZV9zZWxlY3RvchgCIAEoCUgAiAEBQhQKEl93b3JrdHJlZV9zZWxlY3RvciJbChRDbGVhclNlc3Npb25SZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEi8KCXBsYWNlbWVudBgCIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YSK+AQoSRm9ya1Nlc3Npb25SZXF1ZXN0EiIKEXNvdXJjZV9zZXNzaW9uX2lkGAEgASgJQge6SARyAhABEg0KBXRpdGxlGAIgASgJEhgKEHJlYXNvbmluZ19lZmZvcnQYAyABKAkSHgoRd29ya3RyZWVfc2VsZWN0b3IYBCABKAlIAIgBARITCgtwcm92aWRlcl9pZBgFIAEoCRIQCghtb2RlbF9pZBgGIAEoCUIUChJfd29ya3RyZWVfc2VsZWN0b3IiWgoTRm9ya1Nlc3Npb25SZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEi8KCXBsYWNlbWVudBgCIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YSI7ChBDb250ZXh0T2NjdXBhbmN5EhQKDGlucHV0X3Rva2VucxgBIAEoAxIRCgllc3RpbWF0ZWQYAiABKAgirAYKB1Nlc3Npb24SEgoKc2Vzc2lvbl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRInCgRtb2RlGAMgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgFIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSDQoFdHVybnMYBiABKAUSEgoKdG9vbF9jYWxscxgHIAEoBRIXCg9jcmVhdGVkX2F0X3VuaXgYCCABKAMSMAoOcmVzb2x2ZWRfbW9kZWwYCSABKAsyGC5tZWNhdGwudjEuUmVzb2x2ZWRNb2RlbBIMCgRraW5kGA4gASgJEjQKDHJlbGF0aW9uc2hpcBgPIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uUmVsYXRpb25zaGlwEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGBAgAygJEhcKD2RlYnVnX21jcF90b29scxgRIAMoCRIvCglwbGFjZW1lbnQYEiABKAsyHC5tZWNhdGwudjEuUGxhY2VtZW50TWV0YWRhdGESLwoOdGl0bGVfbWV0YWRhdGEYEyABKAsyFy5tZWNhdGwudjEuU2Vzc2lvblRpdGxlEjcKC3Rva2VuX3VzYWdlGBQgAygLMiIubWVjYXRsLnYxLlNlc3Npb24uVG9rZW5Vc2FnZUVudHJ5EjwKFHNlc3Npb25fY2FwYWJpbGl0aWVzGBUgASgLMh4ubWVjYXRsLnYxLlNlc3Npb25DYXBhYmlsaXRpZXMSPQoYbGF0ZXN0X2NvbnRleHRfb2NjdXBhbmN5GBYgASgLMhsubWVjYXRsLnYxLkNvbnRleHRPY2N1cGFuY3kaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECAQQBUoECAoQC0oECAsQDEoECAwQDUoECA0QDlIJd29ya3NwYWNlUgV0aXRsZVIMY2FwYWJpbGl0aWVzUhB0aXRsZV9wcm92ZW5hbmNlUhphZG9wdGlvbl9zb3VyY2Vfc2Vzc2lvbl9pZCKVAQoMU2Vzc2lvblRpdGxlEg0KBXRpdGxlGAEgASgJEhIKCnByb3ZlbmFuY2UYAiABKAkSGAoQZ2VuZXJhdGlvbl9zdGF0ZRgDIAEoCRI2Cg5sYXRlc3RfYXR0ZW1wdBgEIAEoCzIeLm1lY2F0bC52MS5UaXRsZUF0dGVtcHRTdW1tYXJ5EhAKCHJldmlzaW9uGAUgASgEIjgKE1RpdGxlQXR0ZW1wdFN1bW1hcnkSCgoCaWQYASABKAkSDwoHb3V0Y29tZRgCIAEoCUoECAMQBCKhAQoKVG9rZW5Vc2FnZRIfCgV0b3RhbBgBIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIxCgZtb2RlbHMYAiADKAsyIS5tZWNhdGwudjEuVG9rZW5Vc2FnZS5Nb2RlbHNFbnRyeRo/CgtNb2RlbHNFbnRyeRILCgNrZXkYASABKAkSHwoFdmFsdWUYAiABKAsyEC5tZWNhdGwudjEuVXNhZ2U6AjgBIsQCCg9Db252ZXJzZVJlcXVlc3QSIwoGcHJvbXB0GAEgASgLMhEubWVjYXRsLnYxLlByb21wdEgAEiYKBXJldHJ5GAIgASgLMhUubWVjYXRsLnYxLlJldHJ5U3RhcnRIABI0Cg9yZXN1bWVfYXBwcm92YWwYCiABKAsyGS5tZWNhdGwudjEuUmVzdW1lQXBwcm92YWxIABIjCgZjYW5jZWwYCyABKAsyES5tZWNhdGwudjEuQ2FuY2VsSAASLgoMY2FuY2VsX2NoaWxkGAwgASgLMhYubWVjYXRsLnYxLkNhbmNlbENoaWxkSAASIQoFc3RlZXIYDSABKAsyEC5tZWNhdGwudjEuU3RlZXJIABIuCgxzdGVlcl9jYW5jZWwYDiABKAsyFi5tZWNhdGwudjEuU3RlZXJDYW5jZWxIAEIGCgRraW5kIjMKEENvbnZlcnNlUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQinAEKB0NvbnRlbnQSJQoEa2luZBgBIAEoDjIXLm1lY2F0bC52MS5Db250ZW50LktpbmQSEQoJbWltZV90eXBlGAIgASgJEgwKBGRhdGEYAyABKAwSCwoDdXJsGAQgASgJIjwKBEtpbmQSFAoQS0lORF9VTlNQRUNJRklFRBAAEg4KCktJTkRfSU1BR0UQARIOCgpLSU5EX0FVRElPEAIikAMKDENvbnRlbnRCbG9jaxIqCgRraW5kGAEgASgOMhwubWVjYXRsLnYxLkNvbnRlbnRCbG9jay5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCRIMCgR0ZXh0GAUgASgJEgwKBG5hbWUYBiABKAkSDQoFdGl0bGUYByABKAkSEwoLZGVzY3JpcHRpb24YCCABKAkSDAoEc2l6ZRgJIAEoAxIQCghhdWRpZW5jZRgKIAMoCRIQCghwcmlvcml0eRgLIAEoARIVCg1sYXN0X21vZGlmaWVkGAwgASgJIpwBCgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABINCglLSU5EX1RFWFQQARIOCgpLSU5EX0lNQUdFEAISDgoKS0lORF9BVURJTxADEhYKEktJTkRfUkVTT1VSQ0VfTElOSxAEEhoKFktJTkRfRU1CRURERURfUkVTT1VSQ0UQBRIbChdLSU5EX1NUUlVDVFVSRURfQ09OVEVOVBAGIikKClJldHJ5U3RhcnQSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJ+CgZQcm9tcHQSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIMCgR0ZXh0GAIgASgJEiEKBXBhcnRzGAMgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSJgoec2VydmVyX293bmVkX3BsYW5fY29udGludWF0aW9uGAQgASgIItcBCg5SZXN1bWVBcHByb3ZhbBIXCgZhc2tfaWQYASABKAlCB7pIBHICEAESOQoHdmVyZGljdBgDIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAxIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkSEQoJcmV2aWV3X2lkGAUgASgJEjgKDmd1YXJkcmFpbF9raW5kGAYgASgOMiAubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsS2luZEoECAIQA1IFYWxsb3ciIQoGQ2FuY2VsEhcKD2V4cGVjdGVkX3J1bl9pZBgBIAEoCSIoCgtDYW5jZWxDaGlsZBIZCghjaGlsZF9pZBgBIAEoCUIHukgEcgIQASJlCgVTdGVlchIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudBIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkiOgoLU3RlZXJDYW5jZWwSEgoKbWVzc2FnZV9pZBgBIAEoCRIXCg9leHBlY3RlZF9ydW5faWQYAiABKAki9gEKFFJlc29sdmVSdW5Bc2tSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIAoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJQge6SARyAhABEhcKBmFza19pZBgDIAEoCUIHukgEcgIQARI5Cgd2ZXJkaWN0GAQgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdEIMukgJggEGGAEYAhgDEhEKCXJldmlld19pZBgFIAEoCRI4Cg5ndWFyZHJhaWxfa2luZBgGIAEoDjIgLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbEtpbmQiNwoVUmVzb2x2ZVJ1bkFza1Jlc3BvbnNlEg4KBnJ1bl9pZBgBIAEoCRIOCgZhc2tfaWQYAiABKAkiqgEKFVJlc29sdmVQbGFuQXNrUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIXCgZhc2tfaWQYAyABKAlCB7pIBHICEAESOQoHdmVyZGljdBgEIAEoDjIaLm1lY2F0bC52MS5BcHByb3ZhbFZlcmRpY3RCDLpICYIBBhgBGAIYAyI4ChZSZXNvbHZlUGxhbkFza1Jlc3BvbnNlEg4KBnJ1bl9pZBgBIAEoCRIOCgZhc2tfaWQYAiABKAkiUQoQQ2FuY2VsUnVuUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQASIjChFDYW5jZWxSdW5SZXNwb25zZRIOCgZydW5faWQYASABKAkikAIKD1N0ZWVyUnVuUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIMCgR0ZXh0GAMgASgJEisKBXBhcnRzGAQgAygLMhIubWVjYXRsLnYxLkNvbnRlbnRCCLpIBZIBAhAQEhsKCm1lc3NhZ2VfaWQYBSABKAlCB7pIBHICGEA6ZrpIYxphChFzdGVlcl9ydW4uY29udGVudBIjdGV4dCBhbmQgcGFydHMgY2Fubm90IGJvdGggYmUgZW1wdHkaJ3RoaXMudGV4dCAhPSAnJyB8fCBzaXplKHRoaXMucGFydHMpID4gMCJgChBTdGVlclJ1blJlc3BvbnNlEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEg4KBnJ1bl9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJInMKFUNhbmNlbFJ1blN0ZWVyUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiAKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCUIHukgEcgIQARIbCgptZXNzYWdlX2lkGAMgASgJQge6SARyAhhAImYKFkNhbmNlbFJ1blN0ZWVyUmVzcG9uc2USKAoHb3V0Y29tZRgBIAEoDjIXLm1lY2F0bC52MS5TdGVlck91dGNvbWUSDgoGcnVuX2lkGAIgASgJEhIKCm1lc3NhZ2VfaWQYAyABKAkiaAomR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIhChBhdXRob3JpemF0aW9uX2lkGAIgASgJQge6SARyAhABIjYKJ0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRILCgN1cmwYASABKAkitAEKHlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhgKEGF1dGhvcml6YXRpb25faWQYAiABKAkSNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAQgkKB2NvbnRyb2wiQgofUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKzAQodQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkEKHkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKQAQoNQXV0aG9yaXphdGlvbhIYChBhdXRob3JpemF0aW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGc3RhdHVzGAQgASgJEhQKDGRpc3BsYXlfbmFtZRgFIAEoCSI+ChdQbGFuQ29udGludWF0aW9uRmFpbHVyZRITCgtwbGFuX3J1bl9pZBgBIAEoCRIOCgZhc2tfaWQYAiABKAkitwcKBUV2ZW50EgwKBHR5cGUYASABKAkSCwoDc2VxGAIgASgDEgwKBHR1cm4YAyABKAUSDAoEdGV4dBgEIAEoCRImCgl0b29sX2NhbGwYBSABKAsyEy5tZWNhdGwudjEuVG9vbENhbGwSKgoLdG9vbF9yZXN1bHQYBiABKAsyFS5tZWNhdGwudjEuVG9vbFJlc3VsdBIlCgNhc2sYByABKAsyGC5tZWNhdGwudjEuUGVybWlzc2lvbkFzaxIhCgZyZXN1bHQYCCABKAsyES5tZWNhdGwudjEuUmVzdWx0EiQKCHR1cm5fZW5kGAogASgLMhIubWVjYXRsLnYxLlR1cm5FbmQSHQoEaG9vaxgLIAEoCzIPLm1lY2F0bC52MS5Ib29rEiUKCHN1YmFnZW50GAwgASgLMhMubWVjYXRsLnYxLlN1YmFnZW50Eh0KBHRlYW0YDSABKAsyDy5tZWNhdGwudjEuVGVhbRIlCghwYXJhbGxlbBgOIAEoCzITLm1lY2F0bC52MS5QYXJhbGxlbBIsCghzY2hlZHVsZRgPIAEoCzIaLm1lY2F0bC52MS5TY2hlZHVsZVBheWxvYWQSJQoIYXBwcm92YWwYECABKAsyEy5tZWNhdGwudjEuQXBwcm92YWwSKgoLdXNlcl9wcm9tcHQYESABKAsyFS5tZWNhdGwudjEuVXNlclByb21wdBI4ChJjb21wYWN0aW9uX2FyY2hpdmUYEiABKAsyHC5tZWNhdGwudjEuQ29tcGFjdGlvbkFyY2hpdmUSIwoFc3RlZXIYEyABKAsyFC5tZWNhdGwudjEuU3RlZXJFY2hvEioKDXN0ZWVyX291dGNvbWUYFCABKAsyEy5tZWNhdGwudjEuU3RlZXJBY2sSKgoLbW9kZWxfcmV0cnkYFSABKAsyFS5tZWNhdGwudjEuTW9kZWxSZXRyeRIOCgZydW5faWQYFiABKAkSJgoFdGl0bGUYFyABKAsyFy5tZWNhdGwudjEuU2Vzc2lvblRpdGxlEi8KDWF1dGhvcml6YXRpb24YGCABKAsyGC5tZWNhdGwudjEuQXV0aG9yaXphdGlvbhIyCg9jb250cm9sX3JlZnVzZWQYGSABKAsyGS5tZWNhdGwudjEuQ29udHJvbFJlZnVzZWQSRQoZcGxhbl9jb250aW51YXRpb25fZmFpbHVyZRgaIAEoCzIiLm1lY2F0bC52MS5QbGFuQ29udGludWF0aW9uRmFpbHVyZUoECAkQClIFdXNhZ2UiMgoOQ29udHJvbFJlZnVzZWQSDgoGYXNrX2lkGAEgASgJEhAKCGNhdGVnb3J5GAIgASgJIngKCk1vZGVsUmV0cnkSNgoRcmV0cnlfZGlzcG9zaXRpb24YASABKA4yGy5tZWNhdGwudjEuUmV0cnlEaXNwb3NpdGlvbhIyCg9zdHJlYW1fcHJvZ3Jlc3MYAiABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3MiUAoJU3RlZXJFY2hvEgwKBHRleHQYASABKAkSEgoKbWVzc2FnZV9pZBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50ImgKCFN0ZWVyQWNrEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEgwKBHRleHQYAiABKAkSEAoIcHJvbW90ZWQYAyABKAgSEgoKbWVzc2FnZV9pZBgEIAEoCSItCgxHdWFyZHJhaWxSZWYSCwoDcmVmGAEgASgJEhAKCGNhdGVnb3J5GAIgASgJIq8DCg9HdWFyZHJhaWxSZXZpZXcSEQoJcmV2aWV3X2lkGAEgASgJEiQKA2pvYhgCIAEoDjIXLm1lY2F0bC52MS5HdWFyZHJhaWxKb2ISMgoKYXNzZXNzbWVudBgDIAEoDjIeLm1lY2F0bC52MS5HdWFyZHJhaWxBc3Nlc3NtZW50EjIKCmluc3BlY3Rpb24YBCABKA4yHi5tZWNhdGwudjEuR3VhcmRyYWlsSW5zcGVjdGlvbhI0CgtkaXNwb3NpdGlvbhgFIAEoDjIfLm1lY2F0bC52MS5HdWFyZHJhaWxEaXNwb3NpdGlvbhITCgtyZWFzb25fY29kZRgGIAEoCRIPCgdydWxlX2lkGAcgASgJEhMKC3J1bGVfb3JpZ2luGAggASgJEhsKE2NoZWNrZXJfcHJvdmlkZXJfaWQYCSABKAkSGAoQY2hlY2tlcl9tb2RlbF9pZBgKIAEoCRIpCghjb25jZXJucxgLIAMoCzIXLm1lY2F0bC52MS5HdWFyZHJhaWxSZWYSKAoHc291cmNlcxgMIAMoCzIXLm1lY2F0bC52MS5HdWFyZHJhaWxSZWYipwEKFkd1YXJkcmFpbEFwcHJvdmFsU2NvcGUSEQoJcmV2aWV3X2lkGAEgASgJEi4KBGtpbmQYAiABKA4yIC5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxLaW5kEhQKDGdyYW50X2RpZ2VzdBgDIAEoCRIUCgxzZXNzaW9uX29ubHkYBCABKAgSGAoQcmVwZWF0X2F2YWlsYWJsZRgFIAEoCEoECAYQByIyChxMaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAki0wEKFkd1YXJkcmFpbENvdmVyYWdlRW50cnkSDAoEdG9vbBgBIAEoCRINCgVwaGFzZRgCIAEoCRIkCgNqb2IYAyABKA4yFy5tZWNhdGwudjEuR3VhcmRyYWlsSm9iEgwKBG1vZGUYBCABKAkSDwoHcnVsZV9pZBgFIAEoCRITCgtydWxlX29yaWdpbhgGIAEoCRIyCgppbnNwZWN0aW9uGAcgASgOMh4ubWVjYXRsLnYxLkd1YXJkcmFpbEluc3BlY3Rpb24SDgoGcmVhc29uGAggASgJIpsBCh1MaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXNwb25zZRIPCgdlbmFibGVkGAEgASgIEhsKE2NoZWNrZXJfcHJvdmlkZXJfaWQYAiABKAkSGAoQY2hlY2tlcl9tb2RlbF9pZBgDIAEoCRIyCgdlbnRyaWVzGAQgAygLMiEubWVjYXRsLnYxLkd1YXJkcmFpbENvdmVyYWdlRW50cnkiSAofR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhEKCXJldmlld19pZBgCIAEoCSJzCiBHZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXNwb25zZRIRCglyZXZpZXdfaWQYASABKAkSDwoHY29uY2VybhgCIAEoCRIWCg5zb3VyY2VfZGlzcGxheRgDIAEoCRITCgtuZXh0X2FjdGlvbhgEIAEoCSKQAQoIQXBwcm92YWwSDgoGYXNrX2lkGAEgASgJEgwKBHRvb2wYAyABKAkSDwoHY2FsbF9pZBgEIAEoCRIrCgd2ZXJkaWN0GAYgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdBIOCgZvcmlnaW4YByABKAlKBAgCEANKBAgFEAZSDGFsbG93X2Fsd2F5cyJQCgpVc2VyUHJvbXB0EgwKBHRleHQYASABKAkSIQoFcGFydHMYAiADKAsyEi5tZWNhdGwudjEuQ29udGVudBIRCglzeW50aGV0aWMYAyABKAgiRQoRQ29tcGFjdGlvbkFyY2hpdmUSMAoIcmVwbGFjZWQYASADKAsyHi5tZWNhdGwudjEuQ29udmVyc2F0aW9uTWVzc2FnZSLvAQoTQ29udmVyc2F0aW9uTWVzc2FnZRIMCgRyb2xlGAEgASgJEgwKBHRleHQYAiABKAkSJwoKdG9vbF9jYWxscxgDIAMoCzITLm1lY2F0bC52MS5Ub29sQ2FsbBIqCgt0b29sX3Jlc3VsdBgEIAEoCzIVLm1lY2F0bC52MS5Ub29sUmVzdWx0EhEKCXJlYXNvbmluZxgFIAEoCRIWCg5wcm92aWRlcl9waGFzZRgGIAEoCRIhCgVwYXJ0cxgHIAMoCzISLm1lY2F0bC52MS5Db250ZW50EhkKEXJlYXNvbmluZ19pdGVtX2lkGAggASgJInYKD1NjaGVkdWxlUGF5bG9hZBIVCg1zY2hlZHVsZV9uYW1lGAEgASgJEg8KB2ZpcmVfaWQYAiABKAkSEgoKc2Vzc2lvbl9pZBgDIAEoCRIMCgRraW5kGAQgASgJEgwKBHN0b3AYBSABKAkSCwoDZXJyGAYgASgJIo4BCgRIb29rEg0KBXBoYXNlGAEgASgJEgwKBHRvb2wYAiABKAkSKQoIZGVjaXNpb24YAyABKA4yFy5tZWNhdGwudjEuSG9va0RlY2lzaW9uEg8KB2NhbGxfaWQYBCABKAkSLQoJZ3VhcmRyYWlsGAUgASgLMhoubWVjYXRsLnYxLkd1YXJkcmFpbFJldmlldyKoAgoPUm91dGluZ0RlY2lzaW9uEg8KB2JhY2tlbmQYASABKAkSGAoQY2xhc3NpZmllcl9tb2RlbBgCIAEoCRIaChJjYW5kaWRhdGVfY2F0ZWdvcnkYAyABKAkSFwoPY2FuZGlkYXRlX21vZGVsGAQgASgJEhcKCmNvbmZpZGVuY2UYBSABKAFIAIgBARIfChJtaW5pbXVtX2NvbmZpZGVuY2UYBiABKAFIAYgBARIPCgdvdXRjb21lGAcgASgJEhoKEmNvbnNlY3V0aXZlX21pc3NlcxgIIAEoBRISCgptaXNzX2xpbWl0GAkgASgFEhQKDGJyZWFrZXJfb3BlbhgKIAEoCEINCgtfY29uZmlkZW5jZUIVChNfbWluaW11bV9jb25maWRlbmNlIooECghTdWJhZ2VudBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIQCghjaGlsZF9pZBgCIAEoCRIMCgRnb2FsGAMgASgJEhEKCXRvb2xfbmFtZRgEIAEoCRIQCghpc19lcnJvchgFIAEoCBISCgp0b29sX2NvdW50GAYgASgFEh8KBXVzYWdlGAcgASgLMhAubWVjYXRsLnYxLlVzYWdlEgwKBHN0b3AYCCABKAkSEwoLZHVyYXRpb25fbXMYCSABKAMSEgoKYmFja2dyb3VuZBgKIAEoCBIXCg9yb3V0ZWRfY2F0ZWdvcnkYCyABKAkSFAoMcm91dGVkX21vZGVsGAwgASgJEg0KBW1vZGVsGA0gASgJEhIKCmlubmVyX2tpbmQYDiABKAkSDAoEdGV4dBgPIAEoCRIOCgZkZXRhaWwYECABKAkSDQoFY2F1c2UYESABKAkSFgoOcm91dGluZ19yZWFzb24YEiABKAkSOQoQcm91dGluZ19kZWNpc2lvbhgTIAEoCzIaLm1lY2F0bC52MS5Sb3V0aW5nRGVjaXNpb25IAIgBARIaChJjaGlsZF90b29sX2NhbGxfaWQYFCABKAkSEAoIcHJvdmlkZXIYFSABKAkSIAoYZXhwbGljaXRfcm91dGVyX2NhdGVnb3J5GBYgASgJQhMKEV9yb3V0aW5nX2RlY2lzaW9uIqYCCg5UZWFtTWVtYmVyU3BlYxIMCgRuYW1lGAEgASgJEgwKBHJvbGUYAiABKAkSEAoIbXV0YXRpbmcYAyABKAgSDAoEbGVhZBgEIAEoCBIXCg9yb3V0ZWRfY2F0ZWdvcnkYBSABKAkSFAoMcm91dGVkX21vZGVsGAYgASgJEg0KBW1vZGVsGAcgASgJEhYKDnJvdXRpbmdfcmVhc29uGAggASgJEjkKEHJvdXRpbmdfZGVjaXNpb24YCSABKAsyGi5tZWNhdGwudjEuUm91dGluZ0RlY2lzaW9uSACIAQESEAoIcHJvdmlkZXIYCiABKAkSIAoYZXhwbGljaXRfcm91dGVyX2NhdGVnb3J5GAsgASgJQhMKEV9yb3V0aW5nX2RlY2lzaW9uIvoDCgRUZWFtEhYKDnBhcmVudF9jYWxsX2lkGAEgASgJEg8KB3RlYW1faWQYAiABKAkSKQoGcm9zdGVyGAMgAygLMhkubWVjYXRsLnYxLlRlYW1NZW1iZXJTcGVjEg4KBm1lbWJlchgEIAEoCRISCgppbm5lcl9raW5kGAUgASgJEgwKBHRleHQYBiABKAkSEQoJdG9vbF9uYW1lGAcgASgJEg4KBmRldGFpbBgIIAEoCRIQCghpc19lcnJvchgJIAEoCBIOCgZyb3VuZHMYCiABKAUSDAoEc3RvcBgLIAEoCRIfCgV1c2FnZRgMIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRIUCgxjb250ZXh0X3VzZWQYDSABKAMSFgoOY29udGV4dF93aW5kb3cYDiABKAMSIgoFdGFza3MYDyADKAsyEy5tZWNhdGwudjEuVGVhbVRhc2sSKAoIZmluZGluZ3MYECADKAsyFi5tZWNhdGwudjEuVGVhbUZpbmRpbmcSNgoMZGlzcG9zaXRpb25zGBEgAygLMiAubWVjYXRsLnYxLlRlYW1NZW1iZXJEaXNwb3NpdGlvbhIZChFtZW1iZXJfc2Vzc2lvbl9pZBgSIAEoCRINCgVjYXVzZRgTIAEoCRIaChJjaGlsZF90b29sX2NhbGxfaWQYFCABKAkijgUKCFBhcmFsbGVsEhYKDnBhcmVudF9jYWxsX2lkGAEgASgJEgwKBGtpbmQYAiABKAkSDAoEam9pbhgDIAEoCRIUCgxicmFuY2hfY291bnQYBCABKAUSFAoMYnJhbmNoX2luZGV4GAUgASgFEhQKDGJyYW5jaF9sYWJlbBgGIAEoCRIMCgRnb2FsGAcgASgJEhEKCXRvb2xfbmFtZRgIIAEoCRIQCghpc19lcnJvchgJIAEoCBISCgp0b29sX2NvdW50GAogASgFEg4KBmZhaWxlZBgLIAEoCBIMCgRzdG9wGA0gASgJEh8KBXVzYWdlGA4gASgLMhAubWVjYXRsLnYxLlVzYWdlEhMKC2R1cmF0aW9uX21zGA8gASgDEg4KBndpbm5lchgQIAEoBRIQCghjaGlsZF9pZBgSIAEoCRIXCg9yb3V0ZWRfY2F0ZWdvcnkYEyABKAkSFAoMcm91dGVkX21vZGVsGBQgASgJEg0KBW1vZGVsGBUgASgJEhIKCmlubmVyX2tpbmQYFiABKAkSDAoEdGV4dBgXIAEoCRIOCgZkZXRhaWwYGCABKAkSFgoOcm91dGluZ19yZWFzb24YGSABKAkSOQoQcm91dGluZ19kZWNpc2lvbhgaIAEoCzIaLm1lY2F0bC52MS5Sb3V0aW5nRGVjaXNpb25IAIgBARIaChJjaGlsZF90b29sX2NhbGxfaWQYGyABKAkSEAoIcHJvdmlkZXIYHCABKAkSIAoYZXhwbGljaXRfcm91dGVyX2NhdGVnb3J5GB0gASgJQhMKEV9yb3V0aW5nX2RlY2lzaW9uSgQIDBANSgQIERASUgl3b3Jrc3BhY2VSEHdpbm5lcl93b3Jrc3BhY2UiMgoIVG9vbENhbGwSCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRhcmdzGAMgASgJIoUBCgpUb29sUmVzdWx0Eg8KB2NhbGxfaWQYASABKAkSDwoHY29udGVudBgCIAEoCRIQCghpc19lcnJvchgDIAEoCBInCgZibG9ja3MYBCADKAsyFy5tZWNhdGwudjEuQ29udGVudEJsb2NrEhoKEnN0cnVjdHVyZWRfY29udGVudBgFIAEoCSKjAQoNUGVybWlzc2lvbkFzaxIOCgZhc2tfaWQYASABKAkSDAoEdG9vbBgCIAEoCRIMCgRhcmdzGAMgASgJEg4KBnJlYXNvbhgEIAEoCRI0CglndWFyZHJhaWwYBSABKAsyIS5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxTY29wZRIUCgdjYWxsX2lkGAYgASgJSACIAQFCCgoIX2NhbGxfaWQihQIKBlJlc3VsdBIMCgRzdG9wGAEgASgJEgwKBHRleHQYAiABKAkSHwoFdXNhZ2UYAyABKAsyEC5tZWNhdGwudjEuVXNhZ2USDQoFZXJyb3IYBCABKAkSOwoRcmV0cnlfZGlzcG9zaXRpb24YBiABKA4yGy5tZWNhdGwudjEuUmV0cnlEaXNwb3NpdGlvbkgAiAEBEjcKD3N0cmVhbV9wcm9ncmVzcxgHIAEoDjIZLm1lY2F0bC52MS5TdHJlYW1Qcm9ncmVzc0gBiAEBQhQKEl9yZXRyeV9kaXNwb3NpdGlvbkISChBfc3RyZWFtX3Byb2dyZXNzSgQIBRAGUglwZXJtYW5lbnQiUgoHVHVybkVuZBIfCgV1c2FnZRgBIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgCIAEoAxIRCgllc3RpbWF0ZWQYAyABKAgihQEKBVVzYWdlEhQKDGlucHV0X3Rva2VucxgBIAEoAxIVCg1vdXRwdXRfdG9rZW5zGAIgASgDEhkKEWNhY2hlX3JlYWRfdG9rZW5zGAMgASgDEhoKEmNhY2hlX3dyaXRlX3Rva2VucxgEIAEoAxIYChByZWFzb25pbmdfdG9rZW5zGAUgASgDIpABCgtNY3BSZXNvdXJjZRIOCgZzZXJ2ZXIYASABKAkSCwoDdXJpGAIgASgJEgwKBG5hbWUYAyABKAkSDQoFdGl0bGUYBCABKAkSEwoLZGVzY3JpcHRpb24YBSABKAkSEQoJbWltZV90eXBlGAYgASgJEgwKBHNpemUYByABKAMSEQoJcmVhZF9vbmx5GAggASgIIikKF0xpc3RNY3BSZXNvdXJjZXNSZXF1ZXN0Eg4KBnNlcnZlchgBIAEoCSJFChhMaXN0TWNwUmVzb3VyY2VzUmVzcG9uc2USKQoJcmVzb3VyY2VzGAEgAygLMhYubWVjYXRsLnYxLk1jcFJlc291cmNlIlEKE01jcFJlc291cmNlQ29udGVudHMSCwoDdXJpGAEgASgJEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgR0ZXh0GAMgASgJEgwKBGJsb2IYBCABKAwiRwoWUmVhZE1jcFJlc291cmNlUmVxdWVzdBIXCgZzZXJ2ZXIYASABKAlCB7pIBHICEAESFAoDdXJpGAIgASgJQge6SARyAhABIksKF1JlYWRNY3BSZXNvdXJjZVJlc3BvbnNlEjAKCGNvbnRlbnRzGAEgAygLMh4ubWVjYXRsLnYxLk1jcFJlc291cmNlQ29udGVudHMiVwoRTWNwUHJvbXB0QXJndW1lbnQSDAoEbmFtZRgBIAEoCRINCgV0aXRsZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRIQCghyZXF1aXJlZBgEIAEoCCJ+CglNY3BQcm9tcHQSDgoGc2VydmVyGAEgASgJEgwKBG5hbWUYAiABKAkSDQoFdGl0bGUYAyABKAkSEwoLZGVzY3JpcHRpb24YBCABKAkSLwoJYXJndW1lbnRzGAUgAygLMhwubWVjYXRsLnYxLk1jcFByb21wdEFyZ3VtZW50IicKFUxpc3RNY3BQcm9tcHRzUmVxdWVzdBIOCgZzZXJ2ZXIYASABKAkiPwoWTGlzdE1jcFByb21wdHNSZXNwb25zZRIlCgdwcm9tcHRzGAEgAygLMhQubWVjYXRsLnYxLk1jcFByb21wdCK5AQoTR2V0TWNwUHJvbXB0UmVxdWVzdBIXCgZzZXJ2ZXIYASABKAlCB7pIBHICEAESFQoEbmFtZRgCIAEoCUIHukgEcgIQARJACglhcmd1bWVudHMYAyADKAsyLS5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVxdWVzdC5Bcmd1bWVudHNFbnRyeRowCg5Bcmd1bWVudHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIi4KEE1jcFByb21wdE1lc3NhZ2USDAoEcm9sZRgBIAEoCRIMCgR0ZXh0GAIgASgJIloKFEdldE1jcFByb21wdFJlc3BvbnNlEhMKC2Rlc2NyaXB0aW9uGAEgASgJEi0KCG1lc3NhZ2VzGAIgAygLMhsubWVjYXRsLnYxLk1jcFByb21wdE1lc3NhZ2UiTAoNTWNwU2VydmVySW5mbxIMCgRuYW1lGAEgASgJEgsKA3VybBgCIAEoCRIRCgl0cmFuc3BvcnQYAyABKAkSDQoFZ3JvdXAYBCABKAkihwEKCU1jcFNvdXJjZRIMCgRuYW1lGAEgASgJEgwKBGtpbmQYAiABKAkSDwoHZW5hYmxlZBgDIAEoCBINCgVncm91cBgEIAEoCRIpCgdzZXJ2ZXJzGAUgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlckluZm8SEwoLZGlhZ25vc3RpY3MYBiADKAkiFwoVTGlzdE1jcFNvdXJjZXNSZXF1ZXN0InUKFkxpc3RNY3BTb3VyY2VzUmVzcG9uc2USJQoHc291cmNlcxgBIAMoCzIULm1lY2F0bC52MS5NY3BTb3VyY2USEAoIcmV2aXNpb24YAiABKAQSDQoFc3RhbGUYAyABKAgSEwoLcmVjb25jaWxpbmcYBCABKAgiNwoYUmVmcmVzaE1jcFNvdXJjZXNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiPgoZUmVmcmVzaE1jcFNvdXJjZXNSZXNwb25zZRIQCghyZXZpc2lvbhgBIAEoBBIPCgdjaGFuZ2VkGAIgASgIIhsKGUxpc3RUb29sSGl2ZUdyb3Vwc1JlcXVlc3QiLAoaTGlzdFRvb2xIaXZlR3JvdXBzUmVzcG9uc2USDgoGZ3JvdXBzGAEgAygJInQKCUFnZW50SW5mbxIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg0KBW1vZGVsGAMgASgJEg0KBXRvb2xzGAQgAygJEhcKD3Blcm1pc3Npb25fbW9kZRgFIAEoCRINCgVjb2xvchgGIAEoCSITChFMaXN0QWdlbnRzUmVxdWVzdCI6ChJMaXN0QWdlbnRzUmVzcG9uc2USJAoGYWdlbnRzGAEgAygLMhQubWVjYXRsLnYxLkFnZW50SW5mbyIsCgdDb21tYW5kEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkiMgoTTGlzdENvbW1hbmRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjwKFExpc3RDb21tYW5kc1Jlc3BvbnNlEiQKCGNvbW1hbmRzGAEgAygLMhIubWVjYXRsLnYxLkNvbW1hbmQiaQoIV29ya3RyZWUSEAoIc2VsZWN0b3IYASABKAkSDAoEa2luZBgCIAEoCRINCgVsYWJlbBgDIAEoCRIOCgZicmFuY2gYBCABKAkSEAoIcmV2aXNpb24YBSABKAkSDAoEYmFyZRgGIAEoCCIzChRMaXN0V29ya3RyZWVzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIj8KFUxpc3RXb3JrdHJlZXNSZXNwb25zZRImCgl3b3JrdHJlZXMYASADKAsyEy5tZWNhdGwudjEuV29ya3RyZWUicAoJU2tpbGxJbmZvEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEwoLYWdlbnRfb3duZWQYAyABKAgSEwoLb3duZXJfYWdlbnQYBCABKAkSFgoOYWN0aXZlX3ZlcnNpb24YBSABKAkiEwoRTGlzdFNraWxsc1JlcXVlc3QiOgoSTGlzdFNraWxsc1Jlc3BvbnNlEiQKBnNraWxscxgBIAMoCzIULm1lY2F0bC52MS5Ta2lsbEluZm8iQQoNU2tpbGxGaWxlSW5mbxIMCgRuYW1lGAEgASgJEgwKBHNpemUYAiABKAMSFAoMaW5zdHJ1Y3Rpb25zGAMgASgIIi4KFUxpc3RTa2lsbEZpbGVzUmVxdWVzdBIVCgRuYW1lGAEgASgJQge6SARyAhABIkEKFkxpc3RTa2lsbEZpbGVzUmVzcG9uc2USJwoFZmlsZXMYASADKAsyGC5tZWNhdGwudjEuU2tpbGxGaWxlSW5mbyJEChRSZWFkU2tpbGxGaWxlUmVxdWVzdBIVCgRuYW1lGAEgASgJQge6SARyAhABEhUKBGZpbGUYAiABKAlCB7pIBHICEAEiKAoVUmVhZFNraWxsRmlsZVJlc3BvbnNlEg8KB2NvbnRlbnQYASABKAkioQEKCFNvdWxJbmZvEg8KB2NvbnRlbnQYASABKAkSEgoKc2l6ZV9ieXRlcxgCIAEoAxIOCgZzaGEyNTYYAyABKAkSDwoHcHJlc2VudBgEIAEoCBItCgpwcm92ZW5hbmNlGAUgASgOMhkubWVjYXRsLnYxLlNvdWxQcm92ZW5hbmNlEg8KB3RydXN0ZWQYBiABKAgSDwoHZHJpZnRlZBgHIAEoCCIQCg5HZXRTb3VsUmVxdWVzdCI0Cg9HZXRTb3VsUmVzcG9uc2USIQoEc291bBgBIAEoCzITLm1lY2F0bC52MS5Tb3VsSW5mbyIyCg5Vc2VyTW9kZWxFbnRyeRILCgNrZXkYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkiIgoTR2V0VXNlck1vZGVsUmVxdWVzdBILCgNrZXkYASABKAkilgIKEVVzZXJNb2RlbFJldmlzaW9uEgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRIPCgd2ZXJzaW9uGAQgASgJEg4KBnN0YXR1cxgFIAEoCRIOCgZ3cml0ZXIYBiABKAkSDgoGb3JpZ2luGAcgASgJEhkKEXNvdXJjZV9zZXNzaW9uX2lkGAggASgJEhoKEnNvdXJjZV9wcm9wb3NhbF9pZBgJIAEoCRIuCgp1cGRhdGVkX2F0GAsgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEoECAoQC1IPc291cmNlX2V2ZW50X2lkUhFzb3VyY2VfbWVzc2FnZV9pZCKKAQoPVXNlck1vZGVsRGV0YWlsEi0KB2N1cnJlbnQYASABKAsyHC5tZWNhdGwudjEuVXNlck1vZGVsUmV2aXNpb24SLQoHaGlzdG9yeRgCIAMoCzIcLm1lY2F0bC52MS5Vc2VyTW9kZWxSZXZpc2lvbhIZChFoaXN0b3J5X2F2YWlsYWJsZRgDIAEoCCKSAQoUR2V0VXNlck1vZGVsUmVzcG9uc2USKgoHZW50cmllcxgBIAMoCzIZLm1lY2F0bC52MS5Vc2VyTW9kZWxFbnRyeRISCgpzaXplX2J5dGVzGAIgASgDEg4KBnNoYTI1NhgDIAEoCRIqCgZkZXRhaWwYBCABKAsyGi5tZWNhdGwudjEuVXNlck1vZGVsRGV0YWlsIpIBCglNb2RlbEluZm8SCgoCaWQYASABKAkSEwoLcHJvdmlkZXJfaWQYAiABKAkSFAoMZGlzcGxheV9uYW1lGAMgASgJEg0KBWltYWdlGAQgASgIEhEKCXJlYXNvbmluZxgFIAEoCBIVCg1jb250ZXh0X2xpbWl0GAYgASgDEhUKDXByb21wdF9jYWNoZWQYByABKAgiEwoRTGlzdE1vZGVsc1JlcXVlc3QimwEKDlByb3ZpZGVyU3RhdHVzEhMKC3Byb3ZpZGVyX2lkGAEgASgJEg0KBXN0YXRlGAIgASgJEgwKBGhpbnQYAyABKAkSIwobZGVmYXVsdF9tb2RlbF9hdXRvX3NlbGVjdGVkGAQgASgIEhMKC21vZGVsX2NvdW50GAUgASgFEh0KFWF2YWlsYWJsZV9ub3RfZGVmYXVsdBgGIAEoCCJuChJMaXN0TW9kZWxzUmVzcG9uc2USJAoGbW9kZWxzGAEgAygLMhQubWVjYXRsLnYxLk1vZGVsSW5mbxIyCg9wcm92aWRlcl9zdGF0dXMYAiADKAsyGS5tZWNhdGwudjEuUHJvdmlkZXJTdGF0dXMiQQoVUmVmbGVjdFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAFKBAgCEANSBWFzeW5jIrkBChFSZWZsZWN0aW9uUmVjZWlwdBIVCg1yZWZsZWN0aW9uX2lkGAEgASgJEhMKC2Rpc3Bvc2l0aW9uGAIgASgJEg4KBnF1ZXVlZBgDIAEoBRIRCglhYnN0YWluZWQYBCABKAgSDgoGc3RhZ2VkGAUgASgFEhAKCHByb21vdGVkGAYgASgFEhIKCmNvbmZsaWN0ZWQYByABKAUSDgoGcmVhc29uGAggASgJEg8KB21lc3NhZ2UYCSABKAkiRwoWUmVmbGVjdFNlc3Npb25SZXNwb25zZRItCgdyZWNlaXB0GAEgASgLMhwubWVjYXRsLnYxLlJlZmxlY3Rpb25SZWNlaXB0IvECCg9MZWFybmluZ0F0dGVtcHQSCgoCaWQYASABKAkSDwoHdmVyc2lvbhgCIAEoCRINCgVzdGF0ZRgDIAEoCRIPCgdvdXRjb21lGAQgASgJEhQKDGZhaWx1cmVfY29kZRgFIAEoCRIaChJhdHRlbXB0X2dlbmVyYXRpb24YBiABKAQSGAoQY2xhaW1fZ2VuZXJhdGlvbhgHIAEoBBI0ChBjbGFpbV9leHBpcmVzX2F0GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIYChBjaGVja3BvaW50X3N0YWdlGAkgASgJEhMKC3Byb3Bvc2FsX2lkGAogASgJEhAKCHNraWxsX2lkGAsgASgJEi4KCmNyZWF0ZWRfYXQYDCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYDSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIjAKGUdldExlYXJuaW5nQXR0ZW1wdFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAEiSQoaR2V0TGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USKwoHYXR0ZW1wdBgBIAEoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQiSwobTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXF1ZXN0Eg0KBXN0YXRlGAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBSJhChxMaXN0TGVhcm5pbmdBdHRlbXB0c1Jlc3BvbnNlEiwKCGF0dGVtcHRzGAEgAygLMhoubWVjYXRsLnYxLkxlYXJuaW5nQXR0ZW1wdBITCgtuZXh0X2N1cnNvchgCIAEoCSJWChxNdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEiEKEGV4cGVjdGVkX3ZlcnNpb24YAiABKAlCB7pIBHICEAEiTAodTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USKwoHYXR0ZW1wdBgBIAEoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQiXgocTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVxdWVzdBIOCgZzdGF0dXMYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFEg8KB3Byb2plY3QYBCABKAkivgEKE0xlYXJuaW5nRXZpZGVuY2VSZWYSEgoKc2Vzc2lvbl9pZBgBIAEoCRIPCgdsb2NhdG9yGAIgASgJEg8KB29yZGluYWwYAyABKAUSEQoJZXZlbnRfc2VxGAQgASgDEhQKDHRvb2xfY2FsbF9pZBgFIAEoCRIOCgZkaWdlc3QYBiABKAkSEQoJYXZhaWxhYmxlGAcgASgIEhQKDGF2YWlsYWJpbGl0eRgIIAEoCRIPCgdwcmV2aWV3GAkgASgJImcKEExlYXJuaW5nRGVjaXNpb24SDAoEa2luZBgBIAEoCRINCgVhY3RvchgCIAEoCRIOCgZyZWFzb24YAyABKAkSJgoCYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wInkKGExlYXJuaW5nUHJvbW90aW9uUmVjZWlwdBISCgptZW1vcnlfa2V5GAEgASgJEhcKD3ByZXZpb3VzX2V4aXN0cxgCIAEoCBIYChBwcmV2aW91c192ZXJzaW9uGAMgASgJEhYKDnJlc3VsdF92ZXJzaW9uGAQgASgJIpwEChBMZWFybmluZ1Byb3Bvc2FsEgoKAmlkGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSDgoGc3RhdHVzGAMgASgJEgwKBGtpbmQYBCABKAkSCwoDa2V5GAUgASgJEg0KBXZhbHVlGAYgASgJEhMKC2Rlc2NyaXB0aW9uGAcgASgJEg0KBXRpdGxlGAggASgJEgwKBGJvZHkYCSABKAkSMAoIZXZpZGVuY2UYCiADKAsyHi5tZWNhdGwudjEuTGVhcm5pbmdFdmlkZW5jZVJlZhIQCgh0cmlnZ2VycxgLIAMoCRIuCglkZWNpc2lvbnMYDCADKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdEZWNpc2lvbhI2Cglwcm9tb3Rpb24YDSABKAsyIy5tZWNhdGwudjEuTGVhcm5pbmdQcm9tb3Rpb25SZWNlaXB0Ei4KCmNyZWF0ZWRfYXQYDiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhYKDnByb2plY3Rfc2NvcGVkGBAgASgIEhsKE3Byb21vdGlvbl9hdmFpbGFibGUYESABKAgSJAoccHJvbW90aW9uX3VuYXZhaWxhYmxlX3JlYXNvbhgSIAEoCRIYChBsZWFybmVkX3NraWxsX2lkGBMgASgJImQKHUxpc3RMZWFybmluZ1Byb3Bvc2Fsc1Jlc3BvbnNlEi4KCXByb3Bvc2FscxgBIAMoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsEhMKC25leHRfY3Vyc29yGAIgASgJIkIKGkdldExlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEg8KB3Byb2plY3QYAiABKAkiTAobR2V0TGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwikwEKHURlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEiEKEGV4cGVjdGVkX3ZlcnNpb24YAiABKAlCB7pIBHICEAESGQoIZGVjaXNpb24YAyABKAlCB7pIBHICEAESDgoGcmVhc29uGAQgASgJEg8KB3Byb2plY3QYBSABKAkiTwoeRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwiZwocVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABEg8KB3Byb2plY3QYAyABKAkiTgodVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVzcG9uc2USLQoIcHJvcG9zYWwYASABKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbCLsAwoTTGVhcm5lZFNraWxsVmVyc2lvbhIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSEAoIcmV2aXNpb24YBCABKAkSDQoFc3RhdGUYBSABKAkSEwoLb3duZXJfYWdlbnQYBiABKAkSEwoLZGVzY3JpcHRpb24YByABKAkSDAoEYm9keRgIIAEoCRISCgpzdXBlcnNlZGVzGAkgASgJEhYKDmV2aWRlbmNlX2NvdW50GAogASgFEjAKCGV2aWRlbmNlGAsgAygLMh4ubWVjYXRsLnYxLkxlYXJuaW5nRXZpZGVuY2VSZWYSLwoLZXZhbHVhdGlvbnMYDCADKAsyGi5tZWNhdGwudjEuU2tpbGxFdmFsdWF0aW9uEi8KCHJlY2VpcHRzGA0gAygLMh0ubWVjYXRsLnYxLlNraWxsQ2hhbmdlUmVjZWlwdBIuCgpjcmVhdGVkX2F0GA4gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIZChFpbnNwZWN0X2F2YWlsYWJsZRgQIAEoCBIWCg51bmRvX2F2YWlsYWJsZRgRIAEoCCKUAQoPU2tpbGxFdmFsdWF0aW9uEg8KB3ZlcmRpY3QYASABKAkSEwoLZml4dHVyZV9pZHMYAiADKAkSEAoIYmFzZWxpbmUYAyABKAkSEQoJdHJlYXRtZW50GAQgASgJEg4KBnJlYXNvbhgFIAEoCRImCgJhdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiggMKElNraWxsQ2hhbmdlUmVjZWlwdBIKCgJpZBgBIAEoCRIQCghza2lsbF9pZBgCIAEoCRIMCgRuYW1lGAMgASgJEg8KB3ZlcnNpb24YBCABKAkSEQoJb3BlcmF0aW9uGAUgASgJEhIKCmZyb21fc3RhdGUYBiABKAkSEAoIdG9fc3RhdGUYByABKAkSFgoOZXZpZGVuY2VfY291bnQYCCABKAUSGgoSc291cmNlX3Nlc3Npb25faWRzGAkgAygJEhwKFHNvdXJjZV90b29sX2NhbGxfaWRzGAogAygJEg8KB3ZlcmRpY3QYCyABKAkSEwoLZml4dHVyZV9pZHMYDCADKAkSEAoIYmFzZWxpbmUYDSABKAkSEQoJdHJlYXRtZW50GA4gASgJEiYKAmF0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIZChFpbnNwZWN0X2F2YWlsYWJsZRgQIAEoCBIWCg51bmRvX2F2YWlsYWJsZRgRIAEoCCJuChhMaXN0TGVhcm5lZFNraWxsc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUSDQoFc3RhdGUYBCABKAkSEwoLb3duZXJfYWdlbnQYBSABKAkihQEKGUxpc3RMZWFybmVkU2tpbGxzUmVzcG9uc2USLgoGc2tpbGxzGAEgAygLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEwoLbmV4dF9jdXJzb3IYAiABKAkSEgoKZ2VuZXJhdGlvbhgDIAEoBBIPCgdwcm9qZWN0GAQgASgJIm0KFkdldExlYXJuZWRTa2lsbFJlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIPCgd2ZXJzaW9uGAQgASgJIm0KF0dldExlYXJuZWRTa2lsbFJlc3BvbnNlEi0KBXNraWxsGAEgASgLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJIqEBCh9EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESHQoMZnJvbV92ZXJzaW9uGAQgASgJQge6SARyAhABEhsKCnRvX3ZlcnNpb24YBSABKAlCB7pIBHICEAEikQEKIERpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1Jlc3BvbnNlEgwKBGRpZmYYASABKAkSEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJEhAKCHNraWxsX2lkGAQgASgJEhQKDGZyb21fdmVyc2lvbhgFIAEoCRISCgp0b192ZXJzaW9uGAYgASgJIp0BChlNdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESGAoHdmVyc2lvbhgEIAEoCUIHukgEcgIQARIiChFleHBlY3RlZF9yZXZpc2lvbhgFIAEoCUIHukgEcgIQASKnAQoaTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USLQoFc2tpbGwYASABKAsyHi5tZWNhdGwudjEuTGVhcm5lZFNraWxsVmVyc2lvbhISCgpnZW5lcmF0aW9uGAIgASgEEg8KB3Byb2plY3QYAyABKAkSGgoScHVibGljYXRpb25fc3RhdHVzGAQgASgJEhkKEXB1YmxpY2F0aW9uX2Vycm9yGAUgASgJIqYBChtSb2xsYmFja0xlYXJuZWRTa2lsbFJlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIfCg50YXJnZXRfdmVyc2lvbhgEIAEoCUIHukgEcgIQARIiChFleHBlY3RlZF9yZXZpc2lvbhgFIAEoCUIHukgEcgIQASJJChdMaXN0U2tpbGxDaGFuZ2VzUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBSKEAQoYTGlzdFNraWxsQ2hhbmdlc1Jlc3BvbnNlEi4KB2NoYW5nZXMYASADKAsyHS5tZWNhdGwudjEuU2tpbGxDaGFuZ2VSZWNlaXB0EhMKC25leHRfY3Vyc29yGAIgASgJEhIKCmdlbmVyYXRpb24YAyABKAQSDwoHcHJvamVjdBgEIAEoCSKPAQoRQ3JlYXRlVGVhbVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIMCgRuYW1lGAIgASgJEigKB21lbWJlcnMYAyADKAsyFy5tZWNhdGwudjEuVGVhbW1hdGVTcGVjEgwKBGdvYWwYBCABKAkSFwoPbWF4X3RlYW1fdG9rZW5zGAUgASgFIk0KEkNyZWF0ZVRlYW1SZXNwb25zZRIPCgd0ZWFtX2lkGAEgASgJEiYKB21lbWJlcnMYAiADKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlciJxCgxUZWFtbWF0ZVNwZWMSFQoEbmFtZRgBIAEoCUIHukgEcgIQARISCgphZ2VudF90eXBlGAIgASgJEgwKBGxlYWQYAyABKAgSEAoIbXV0YXRpbmcYBCABKAgSFgoOaW5pdGlhbF9wcm9tcHQYBSABKAkikwEKFFNwYXduVGVhbW1hdGVSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESFQoEbmFtZRgCIAEoCUIHukgEcgIQARISCgphZ2VudF90eXBlGAMgASgJEgwKBGxlYWQYBCABKAgSEAoIbXV0YXRpbmcYBSABKAgSFgoOaW5pdGlhbF9wcm9tcHQYBiABKAkiPgoVU3Bhd25UZWFtbWF0ZVJlc3BvbnNlEiUKBm1lbWJlchgBIAEoCzIVLm1lY2F0bC52MS5UZWFtTWVtYmVyInAKGlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESEwoCdG8YAiABKAlCB7pIBHICEAESDAoEZnJvbRgDIAEoCRIVCgRib2R5GAQgASgJQge6SARyAhABIh0KG1NlbmRUZWFtbWF0ZU1lc3NhZ2VSZXNwb25zZSJKChVDYW5jZWxUZWFtbWF0ZVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQARIXCgZtZW1iZXIYAiABKAlCB7pIBHICEAEiGAoWQ2FuY2VsVGVhbW1hdGVSZXNwb25zZSIqCg5SdW5UZWFtUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABImUKCVRlYW1FdmVudBIOCgZtZW1iZXIYASABKAkSHwoFZXZlbnQYAiABKAsyEC5tZWNhdGwudjEuRXZlbnQSJwoHb3V0Y29tZRgDIAEoCzIWLm1lY2F0bC52MS5UZWFtT3V0Y29tZSLbAQoLVGVhbU91dGNvbWUSDgoGcm91bmRzGAEgASgFEhEKCXF1aWVzY2VudBgCIAEoCBIYChBidWRnZXRfZXhoYXVzdGVkGAMgASgIEgwKBHN0b3AYBCABKAkSHwoFdXNhZ2UYBSABKAsyEC5tZWNhdGwudjEuVXNhZ2USNgoMZGlzcG9zaXRpb25zGAYgAygLMiAubWVjYXRsLnYxLlRlYW1NZW1iZXJEaXNwb3NpdGlvbhIoCghmaW5kaW5ncxgHIAMoCzIWLm1lY2F0bC52MS5UZWFtRmluZGluZyIrCg9MaXN0VGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASJxChBMaXN0VGVhbVJlc3BvbnNlEiYKB21lbWJlcnMYASADKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlchIiCgV0YXNrcxgCIAMoCzITLm1lY2F0bC52MS5UZWFtVGFzaxIRCglxdWllc2NlbnQYAyABKAgiUQoKVGVhbU1lbWJlchIMCgRuYW1lGAEgASgJEhIKCmFnZW50X3R5cGUYAiABKAkSDQoFc3RhdGUYAyABKAkSEgoKc2Vzc2lvbl9pZBgEIAEoCSJaCghUZWFtVGFzaxIKCgJpZBgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVzdGF0ZRgDIAEoCRIQCghhc3NpZ25lZRgEIAEoCRIMCgRkZXBzGAUgAygJIisKC1RlYW1GaW5kaW5nEg4KBm1lbWJlchgBIAEoCRIMCgRib2R5GAIgASgJIn0KFVRlYW1NZW1iZXJEaXNwb3NpdGlvbhIMCgRuYW1lGAEgASgJEg8KB3N0b3BwZWQYAiABKAgSLwoGcmVhc29uGAMgASgOMh8ubWVjYXRsLnYxLlRlYW1NZW1iZXJTdG9wUmVhc29uEhQKDGVycm9yX3JvdW5kcxgEIAEoBSIuChJDbGVhbnVwVGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASIVChNDbGVhbnVwVGVhbVJlc3BvbnNlIm8KEkFwcHJvdmVQbGFuUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEi4KC3RhcmdldF9tb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEgwKBG5vdGUYAyABKAkiiQEKF01hbnVhbERyZWFtQ2FwYWJpbGl0aWVzEjgKDnByb2plY3RfbWVtb3J5GAEgASgLMiAubWVjYXRsLnYxLkRyZWFtVGFyZ2V0Q2FwYWJpbGl0eRI0Cgp1c2VyX21vZGVsGAIgASgLMiAubWVjYXRsLnYxLkRyZWFtVGFyZ2V0Q2FwYWJpbGl0eSJVChVEcmVhbVRhcmdldENhcGFiaWxpdHkSEAoIZ2VuZXJhdGUYASABKAgSDgoGZGVjaWRlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCSIqChhHZW5lcmF0ZURyZWFtUGxhblJlcXVlc3QSDgoGdGFyZ2V0GAEgASgJIkUKGUdlbmVyYXRlRHJlYW1QbGFuUmVzcG9uc2USKAoEcGxhbhgBIAEoCzIaLm1lY2F0bC52MS5EcmVhbVJldmlld1BsYW4iOwoWRGVjaWRlRHJlYW1QbGFuUmVxdWVzdBIPCgdwbGFuX2lkGAEgASgJEhAKCGRlY2lzaW9uGAIgASgJIkMKF0RlY2lkZURyZWFtUGxhblJlc3BvbnNlEigKB3JlY2VpcHQYASABKAsyFy5tZWNhdGwudjEuRHJlYW1SZWNlaXB0IssBCg9EcmVhbVJldmlld1BsYW4SCgoCaWQYASABKAkSDgoGdGFyZ2V0GAIgASgJEi4KCmV4cGlyZXNfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEh8KF3BsYW5uZWRfb3BlcmF0aW9uX2NvdW50GAQgASgFEhwKFHBsYW5uZWRfc291cmNlX2NvdW50GAUgASgFEi0KCm9wZXJhdGlvbnMYBiADKAsyGS5tZWNhdGwudjEuRHJlYW1PcGVyYXRpb24i3wEKDkRyZWFtT3BlcmF0aW9uEgwKBGtpbmQYASABKAkSLQoIc3Vydml2b3IYAiABKAsyGy5tZWNhdGwudjEuRHJlYW1QYXJ0aWNpcGFudBIsCgdzb3VyY2VzGAMgAygLMhsubWVjYXRsLnYxLkRyZWFtUGFydGljaXBhbnQSMAoLcmVwbGFjZW1lbnQYBCABKAsyGy5tZWNhdGwudjEuRHJlYW1SZXBsYWNlbWVudBIOCgZyZWFzb24YBSABKAkSIAoYZXhhY3RfZHVwbGljYXRlX2VsaWdpYmxlGAYgASgIIkMKEERyZWFtUGFydGljaXBhbnQSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJIjYKEERyZWFtUmVwbGFjZW1lbnQSDQoFdmFsdWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAki1wEKDERyZWFtUmVjZWlwdBIKCgJpZBgBIAEoCRIOCgZ0YXJnZXQYAiABKAkSEwoLZGlzcG9zaXRpb24YAyABKAkSHAoUcGxhbm5lZF9zb3VyY2VfY291bnQYBCABKAUSHAoUYXBwbGllZF9zb3VyY2VfY291bnQYBSABKAUSHwoXY29uZmxpY3RlZF9zb3VyY2VfY291bnQYBiABKAUSHAoUc2tpcHBlZF9zb3VyY2VfY291bnQYByABKAUSGwoTZmFpbGVkX3NvdXJjZV9jb3VudBgIIAEoBSI0ChVDb21wYWN0U2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASIrChZDb21wYWN0U2Vzc2lvblJlc3BvbnNlEhEKCWNvbXBhY3RlZBgBIAEoCCI3CiFXb3Jrc3BhY2VFbnJvbGxtZW50Q29ubmVjdFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCSJOCiFXb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIVCg1lbnJvbGxtZW50X2lkGAIgASgJInEKE1dvcmtzcGFjZUVucm9sbG1lbnQSFQoNZW5yb2xsbWVudF9pZBgBIAEoCRIOCgZzdGF0dXMYAiABKAkSGQoRcmVxdWlyZWRfc2VydmljZXMYAyABKA0SGAoQcHJlc2VudGF0aW9uX3VybBgEIAEoCSq+AQoOUGVybWlzc2lvbk1vZGUSHwobUEVSTUlTU0lPTl9NT0RFX1VOU1BFQ0lGSUVEEAASGwoXUEVSTUlTU0lPTl9NT0RFX0RFRkFVTFQQARIYChRQRVJNSVNTSU9OX01PREVfUExBThACEiAKHFBFUk1JU1NJT05fTU9ERV9BQ0NFUFRfRURJVFMQAxIYChRQRVJNSVNTSU9OX01PREVfQVVUTxAEEhgKFFBFUk1JU1NJT05fTU9ERV9ZT0xPEAUqkgEKD0FwcHJvdmFsVmVyZGljdBIgChxBUFBST1ZBTF9WRVJESUNUX1VOU1BFQ0lGSUVEEAASGQoVQVBQUk9WQUxfVkVSRElDVF9ERU5ZEAESHwobQVBQUk9WQUxfVkVSRElDVF9BTExPV19PTkNFEAISIQodQVBQUk9WQUxfVkVSRElDVF9BTExPV19BTFdBWVMQAyq+AQoMU3RlZXJPdXRjb21lEh0KGVNURUVSX09VVENPTUVfVU5TUEVDSUZJRUQQABIaChZTVEVFUl9PVVRDT01FX0FDQ0VQVEVEEAESGgoWU1RFRVJfT1VUQ09NRV9BUFBFTkRFRBACEhsKF1NURUVSX09VVENPTUVfUkVUUkFDVEVEEAMSHgoaU1RFRVJfT1VUQ09NRV9OT05FX1BFTkRJTkcQBBIaChZTVEVFUl9PVVRDT01FX1RPT19MQVRFEAUqgAEKDEd1YXJkcmFpbEpvYhIdChlHVUFSRFJBSUxfSk9CX1VOU1BFQ0lGSUVEEAASGAoUR1VBUkRSQUlMX0pPQl9BQ1RJT04QARIZChVHVUFSRFJBSUxfSk9CX0lOQk9VTkQQAhIcChhHVUFSRFJBSUxfSk9CX1BFUk1JU1NJT04QAyqqAQoTR3VhcmRyYWlsQXNzZXNzbWVudBIkCiBHVUFSRFJBSUxfQVNTRVNTTUVOVF9VTlNQRUNJRklFRBAAEiMKH0dVQVJEUkFJTF9BU1NFU1NNRU5UX0FDQ0VQVEFCTEUQARIjCh9HVUFSRFJBSUxfQVNTRVNTTUVOVF9QUk9ISUJJVEVEEAISIwofR1VBUkRSQUlMX0FTU0VTU01FTlRfVU5SRVNPTFZFRBADKowBChNHdWFyZHJhaWxJbnNwZWN0aW9uEiQKIEdVQVJEUkFJTF9JTlNQRUNUSU9OX1VOU1BFQ0lGSUVEEAASIQodR1VBUkRSQUlMX0lOU1BFQ1RJT05fQ09NUExFVEUQARIsCihHVUFSRFJBSUxfSU5TUEVDVElPTl9PUEVSQVRJT05BTF9GQUlMVVJFEAIq0AIKFEd1YXJkcmFpbERpc3Bvc2l0aW9uEiUKIUdVQVJEUkFJTF9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEiEKHUdVQVJEUkFJTF9ESVNQT1NJVElPTl9FWEVDVVRFEAESJAogR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0FTS19BQ1RJT04QAhIpCiVHVUFSRFJBSUxfRElTUE9TSVRJT05fV0lUSEhPTERfUkVTVUxUEAMSKAokR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1JFTEVBU0VfUkVTVUxUEAQSHgoaR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0RFTlkQBRInCiNHVUFSRFJBSUxfRElTUE9TSVRJT05fUEFTU19BRFZJU09SWRAGEioKJkdVQVJEUkFJTF9ESVNQT1NJVElPTl9DT05USU5VRV9XQVJOSU5HEAcqkAEKFUd1YXJkcmFpbEFwcHJvdmFsS2luZBInCiNHVUFSRFJBSUxfQVBQUk9WQUxfS0lORF9VTlNQRUNJRklFRBAAEiIKHkdVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX0FDVElPThABEioKJkdVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX1JFU1VMVF9SRUxFQVNFEAIqmAEKDEhvb2tEZWNpc2lvbhIdChlIT09LX0RFQ0lTSU9OX1VOU1BFQ0lGSUVEEAASFgoSSE9PS19ERUNJU0lPTl9JTkZPEAESGQoVSE9PS19ERUNJU0lPTl9CTE9DS0VEEAISGgoWSE9PS19ERUNJU0lPTl9NT0RJRklFRBADEhoKFkhPT0tfREVDSVNJT05fQURWSVNPUlkQBCqWAQoQUmV0cnlEaXNwb3NpdGlvbhIhCh1SRVRSWV9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEh0KGVJFVFJZX0RJU1BPU0lUSU9OX1VOS05PV04QARIfChtSRVRSWV9ESVNQT1NJVElPTl9SRVRSWUFCTEUQAhIfChtSRVRSWV9ESVNQT1NJVElPTl9QRVJNQU5FTlQQAyqoAQoOU3RyZWFtUHJvZ3Jlc3MSHwobU1RSRUFNX1BST0dSRVNTX1VOU1BFQ0lGSUVEEAASGwoXU1RSRUFNX1BST0dSRVNTX1VOS05PV04QARIdChlTVFJFQU1fUFJPR1JFU1NfUFJFQ09NTUlUEAISGwoXU1RSRUFNX1BST0dSRVNTX1ZJU0lCTEUQAxIcChhTVFJFQU1fUFJPR1JFU1NfQ09NUExFVEUQBCqEAQoOU291bFByb3ZlbmFuY2USHwobU09VTF9QUk9WRU5BTkNFX1VOU1BFQ0lGSUVEEAASGAoUU09VTF9QUk9WRU5BTkNFX1VTRVIQARIbChdTT1VMX1BST1ZFTkFOQ0VfUFJPSkVDVBACEhoKFlNPVUxfUFJPVkVOQU5DRV9EUklWRVIQAyqtAQoUVGVhbU1lbWJlclN0b3BSZWFzb24SJwojVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fVU5TUEVDSUZJRUQQABIhCh1URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9FUlJPUhABEiUKIVRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0NBTkNFTExFRBACEiIKHlRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0JVREdFVBADMpw5Cg5IYXJuZXNzU2VydmljZRJnChRHZXRDb21wYXRpYmlsaXR5SW5mbxImLm1lY2F0bC52MS5HZXRDb21wYXRpYmlsaXR5SW5mb1JlcXVlc3QaJy5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXNwb25zZRJtChZMaXN0RXhlY3V0aW9uVGVtcGxhdGVzEigubWVjYXRsLnYxLkxpc3RFeGVjdXRpb25UZW1wbGF0ZXNSZXF1ZXN0GikubWVjYXRsLnYxLkxpc3RFeGVjdXRpb25UZW1wbGF0ZXNSZXNwb25zZRJSCg1DcmVhdGVTZXNzaW9uEh8ubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXNwb25zZRJSCg1HZXRTZXJ2ZXJJbmZvEh8ubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXF1ZXN0GiAubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXNwb25zZRJJCgpHZXRTZXNzaW9uEhwubWVjYXRsLnYxLkdldFNlc3Npb25SZXF1ZXN0Gh0ubWVjYXRsLnYxLkdldFNlc3Npb25SZXNwb25zZRJqChVMaXN0R3VhcmRyYWlsQ292ZXJhZ2USJy5tZWNhdGwudjEuTGlzdEd1YXJkcmFpbENvdmVyYWdlUmVxdWVzdBooLm1lY2F0bC52MS5MaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXNwb25zZRJzChhHZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWwSKi5tZWNhdGwudjEuR2V0R3VhcmRyYWlsUmV2aWV3RGV0YWlsUmVxdWVzdBorLm1lY2F0bC52MS5HZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXNwb25zZRJnChRHZXRTZXNzaW9uVHJhbnNjcmlwdBImLm1lY2F0bC52MS5HZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QaJy5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRJACgdTZXRNb2RlEhkubWVjYXRsLnYxLlNldE1vZGVSZXF1ZXN0GhoubWVjYXRsLnYxLlNldE1vZGVSZXNwb25zZRJPCgxDbG9zZVNlc3Npb24SHi5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbG9zZVNlc3Npb25SZXNwb25zZRJSCg1SZW5hbWVTZXNzaW9uEh8ubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXNwb25zZRJSCg1EZWxldGVTZXNzaW9uEh8ubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXNwb25zZRJVCg5Db21wYWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5Db21wYWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXNwb25zZRJPCgxDbGVhclNlc3Npb24SHi5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbGVhclNlc3Npb25SZXNwb25zZRJMCgtGb3JrU2Vzc2lvbhIdLm1lY2F0bC52MS5Gb3JrU2Vzc2lvblJlcXVlc3QaHi5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXNwb25zZRJHCghDb252ZXJzZRIaLm1lY2F0bC52MS5Db252ZXJzZVJlcXVlc3QaGy5tZWNhdGwudjEuQ29udmVyc2VSZXNwb25zZSgBMAESUgoNUmVzb2x2ZVJ1bkFzaxIfLm1lY2F0bC52MS5SZXNvbHZlUnVuQXNrUmVxdWVzdBogLm1lY2F0bC52MS5SZXNvbHZlUnVuQXNrUmVzcG9uc2USVQoOUmVzb2x2ZVBsYW5Bc2sSIC5tZWNhdGwudjEuUmVzb2x2ZVBsYW5Bc2tSZXF1ZXN0GiEubWVjYXRsLnYxLlJlc29sdmVQbGFuQXNrUmVzcG9uc2USRgoJQ2FuY2VsUnVuEhsubWVjYXRsLnYxLkNhbmNlbFJ1blJlcXVlc3QaHC5tZWNhdGwudjEuQ2FuY2VsUnVuUmVzcG9uc2USQwoIU3RlZXJSdW4SGi5tZWNhdGwudjEuU3RlZXJSdW5SZXF1ZXN0GhsubWVjYXRsLnYxLlN0ZWVyUnVuUmVzcG9uc2USVQoOQ2FuY2VsUnVuU3RlZXISIC5tZWNhdGwudjEuQ2FuY2VsUnVuU3RlZXJSZXF1ZXN0GiEubWVjYXRsLnYxLkNhbmNlbFJ1blN0ZWVyUmVzcG9uc2USWwoQTGlzdE1jcFJlc291cmNlcxIiLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVzcG9uc2USWAoPUmVhZE1jcFJlc291cmNlEiEubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QaIi5tZWNhdGwudjEuUmVhZE1jcFJlc291cmNlUmVzcG9uc2USVQoOTGlzdE1jcFByb21wdHMSIC5tZWNhdGwudjEuTGlzdE1jcFByb21wdHNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USTwoMR2V0TWNwUHJvbXB0Eh4ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QaHy5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVzcG9uc2USVQoOTGlzdE1jcFNvdXJjZXMSIC5tZWNhdGwudjEuTGlzdE1jcFNvdXJjZXNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVzcG9uc2USXgoRUmVmcmVzaE1jcFNvdXJjZXMSIy5tZWNhdGwudjEuUmVmcmVzaE1jcFNvdXJjZXNSZXF1ZXN0GiQubWVjYXRsLnYxLlJlZnJlc2hNY3BTb3VyY2VzUmVzcG9uc2UScwoYTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzEioubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1JlcXVlc3QaKy5tZWNhdGwudjEuTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVzcG9uc2USYQoSTGlzdFRvb2xIaXZlR3JvdXBzEiQubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1JlcXVlc3QaJS5tZWNhdGwudjEuTGlzdFRvb2xIaXZlR3JvdXBzUmVzcG9uc2USSQoKTGlzdEFnZW50cxIcLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVzcG9uc2USTwoMTGlzdENvbW1hbmRzEh4ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdENvbW1hbmRzUmVzcG9uc2USUgoNTGlzdFdvcmt0cmVlcxIfLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVxdWVzdBogLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVzcG9uc2USUAoTU3RyZWFtU2Vzc2lvbkV2ZW50cxIlLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEkwKEVN0cmVhbVNlc3Npb25MaXZlEiMubWVjYXRsLnYxLlN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmMKEldhdGNoU2Vzc2lvbkV2ZW50cxIkLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0GiUubWVjYXRsLnYxLldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlMAESiAEKH0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb24SMS5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QaMi5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlc3BvbnNlEnQKF1JlY2hlY2tNY3BBdXRob3JpemF0aW9uEikubWVjYXRsLnYxLlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBoqLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlKAEwARJxChZDYW5jZWxNY3BBdXRob3JpemF0aW9uEigubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0GikubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAESTwoMTGlzdFNlc3Npb25zEh4ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdFNlc3Npb25zUmVzcG9uc2USWwoQR2V0U3RvcmFnZUhlYWx0aBIiLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVxdWVzdBojLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVzcG9uc2USYQoSUGxhblNlc3Npb25DbGVhbnVwEiQubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlcXVlc3QaJS5tZWNhdGwudjEuUGxhblNlc3Npb25DbGVhbnVwUmVzcG9uc2USUwoTQXBwbHlTZXNzaW9uQ2xlYW51cBIlLm1lY2F0bC52MS5BcHBseVNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFENhbmNlbFNlc3Npb25DbGVhbnVwEiYubWVjYXRsLnYxLkNhbmNlbFNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFEdldFNlc3Npb25DbGVhbnVwSm9iEiYubWVjYXRsLnYxLkdldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iEkkKCkxpc3RTa2lsbHMSHC5tZWNhdGwudjEuTGlzdFNraWxsc1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdFNraWxsc1Jlc3BvbnNlElUKDkxpc3RTa2lsbEZpbGVzEiAubWVjYXRsLnYxLkxpc3RTa2lsbEZpbGVzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0U2tpbGxGaWxlc1Jlc3BvbnNlElIKDVJlYWRTa2lsbEZpbGUSHy5tZWNhdGwudjEuUmVhZFNraWxsRmlsZVJlcXVlc3QaIC5tZWNhdGwudjEuUmVhZFNraWxsRmlsZVJlc3BvbnNlEkAKB0dldFNvdWwSGS5tZWNhdGwudjEuR2V0U291bFJlcXVlc3QaGi5tZWNhdGwudjEuR2V0U291bFJlc3BvbnNlEk8KDEdldFVzZXJNb2RlbBIeLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldFVzZXJNb2RlbFJlc3BvbnNlElUKDlJlZmxlY3RTZXNzaW9uEiAubWVjYXRsLnYxLlJlZmxlY3RTZXNzaW9uUmVxdWVzdBohLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlc3BvbnNlEmEKEkdldExlYXJuaW5nQXR0ZW1wdBIkLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GiUubWVjYXRsLnYxLkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmcKFExpc3RMZWFybmluZ0F0dGVtcHRzEiYubWVjYXRsLnYxLkxpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBonLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1Jlc3BvbnNlEmkKFFJldHJ5TGVhcm5pbmdBdHRlbXB0EicubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QaKC5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USawoWQWJhbmRvbkxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEl4KEUdlbmVyYXRlRHJlYW1QbGFuEiMubWVjYXRsLnYxLkdlbmVyYXRlRHJlYW1QbGFuUmVxdWVzdBokLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlElgKD0RlY2lkZURyZWFtUGxhbhIhLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXF1ZXN0GiIubWVjYXRsLnYxLkRlY2lkZURyZWFtUGxhblJlc3BvbnNlEmoKFUxpc3RMZWFybmluZ1Byb3Bvc2FscxInLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXF1ZXN0GigubWVjYXRsLnYxLkxpc3RMZWFybmluZ1Byb3Bvc2Fsc1Jlc3BvbnNlEmQKE0dldExlYXJuaW5nUHJvcG9zYWwSJS5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaJi5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEm0KFkRlY2lkZUxlYXJuaW5nUHJvcG9zYWwSKC5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaKS5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEmoKFVVuZG9MZWFybmluZ1Byb21vdGlvbhInLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXF1ZXN0GigubWVjYXRsLnYxLlVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEl4KEUxpc3RMZWFybmVkU2tpbGxzEiMubWVjYXRsLnYxLkxpc3RMZWFybmVkU2tpbGxzUmVxdWVzdBokLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlElgKD0dldExlYXJuZWRTa2lsbBIhLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXF1ZXN0GiIubWVjYXRsLnYxLkdldExlYXJuZWRTa2lsbFJlc3BvbnNlEnMKGERpZmZMZWFybmVkU2tpbGxWZXJzaW9ucxIqLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXF1ZXN0GisubWVjYXRsLnYxLkRpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1Jlc3BvbnNlEmMKFEFjdGl2YXRlTGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYQoSUmVqZWN0TGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYgoTQXJjaGl2ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmUKFFJvbGxiYWNrTGVhcm5lZFNraWxsEiYubWVjYXRsLnYxLlJvbGxiYWNrTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJbChBMaXN0U2tpbGxDaGFuZ2VzEiIubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXF1ZXN0GiMubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXNwb25zZRJJCgpMaXN0TW9kZWxzEhwubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXNwb25zZRJJCgpDcmVhdGVUZWFtEhwubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXF1ZXN0Gh0ubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXNwb25zZRJSCg1TcGF3blRlYW1tYXRlEh8ubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXF1ZXN0GiAubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXNwb25zZRJkChNTZW5kVGVhbW1hdGVNZXNzYWdlEiUubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXF1ZXN0GiYubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXNwb25zZRJVCg5DYW5jZWxUZWFtbWF0ZRIgLm1lY2F0bC52MS5DYW5jZWxUZWFtbWF0ZVJlcXVlc3QaIS5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXNwb25zZRI8CgdSdW5UZWFtEhkubWVjYXRsLnYxLlJ1blRlYW1SZXF1ZXN0GhQubWVjYXRsLnYxLlRlYW1FdmVudDABEkMKCExpc3RUZWFtEhoubWVjYXRsLnYxLkxpc3RUZWFtUmVxdWVzdBobLm1lY2F0bC52MS5MaXN0VGVhbVJlc3BvbnNlEkwKC0NsZWFudXBUZWFtEh0ubWVjYXRsLnYxLkNsZWFudXBUZWFtUmVxdWVzdBoeLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlc3BvbnNlEkAKC0FwcHJvdmVQbGFuEh0ubWVjYXRsLnYxLkFwcHJvdmVQbGFuUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmgKGENvbm5lY3RXb3Jrc3BhY2VTZXJ2aWNlcxIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29ubmVjdFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudBJoChhSZXRyeVdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaQoZQ2FuY2VsV29ya3NwYWNlRW5yb2xsbWVudBIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudEKiAQoNY29tLm1lY2F0bC52MUIMSGFybmVzc1Byb3RvUAFaPmdpdGh1Yi5jb20vc3RhY2tsb2svbWVjYXRsL2NvbnRyYWN0cy9nZW4vZ28vbWVjYXRsL3YxO21lY2F0bHYxogIDTVhYqgIJTWVjYXRsLlYxygIJTWVjYXRsXFYx4gIVTWVjYXRsXFYxXEdQQk1ldGFkYXRh6gIKTWVjYXRsOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_google_protobuf_timestamp]); + fileDesc("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIpgDChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSMAoJZXhlY3V0aW9uGAwgASgLMh0ubWVjYXRsLnYxLkV4ZWN1dGlvblNlbGVjdGlvbhIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMSHQoVYWdlbnRfZGVmaW5pdGlvbl9uYW1lGA0gASgJSgQIARACSgQICBAJSgQIBhAHUgl3b3Jrc3BhY2VSEXNvdXJjZV9zZXNzaW9uX2lkUgdwcm9maWxlImwKEkV4ZWN1dGlvblNlbGVjdGlvbhImCgRub25lGAEgASgLMhgubWVjYXRsLnYxLkV4ZWN1dGlvbk5vbmUSLgoIdGVtcGxhdGUYAiABKAsyHC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGUiDwoNRXhlY3V0aW9uTm9uZSIxChFFeGVjdXRpb25UZW1wbGF0ZRIKCgJpZBgBIAEoCRIQCghyZXZpc2lvbhgCIAEoCSIfCh1MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVxdWVzdCJtCh5MaXN0RXhlY3V0aW9uVGVtcGxhdGVzUmVzcG9uc2USLwoFaXRlbXMYASADKAsyIC5tZWNhdGwudjEuRXhlY3V0aW9uVGVtcGxhdGVJbmZvEhoKEmludmVudG9yeV9yZXZpc2lvbhgCIAEoCSK9AgoVRXhlY3V0aW9uVGVtcGxhdGVJbmZvEi4KCHRlbXBsYXRlGAEgASgLMhwubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSFQoNZGlzcGxheV90b2tlbhgEIAEoCRJECgpleHRlbnNpb25zGAUgAygLMjAubWVjYXRsLnYxLkV4ZWN1dGlvblRlbXBsYXRlSW5mby5FeHRlbnNpb25zRW50cnkSIAoYZGVjbGFyZWRfZXhlY3V0aW9uX2ZpbGVzGAYgASgIEh8KF2RlY2xhcmVkX2J1aWx0X2luX3NoZWxsGAcgASgIGjEKD0V4dGVuc2lvbnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIrEBCg1NY3BTZXJ2ZXJTcGVjEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEgwKBHR5cGUYAyABKAkSDwoHY29tbWFuZBgEIAEoCRI2CgdoZWFkZXJzGAUgAygLMiUubWVjYXRsLnYxLk1jcFNlcnZlclNwZWMuSGVhZGVyc0VudHJ5Gi4KDEhlYWRlcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIisKFEdldFNlcnZlckluZm9SZXF1ZXN0EhMKC3Byb3ZpZGVyX2lkGAEgASgJIm8KFUdldFNlcnZlckluZm9SZXNwb25zZRIQCghidWlsZF9pZBgBIAEoCRIdChVzZXJ2ZXJfaW1wbGVtZW50YXRpb24YAiABKAkSJQodbGxtX3Byb3ZpZGVyX2Rpc3BsYXlfZW5kcG9pbnQYAyABKAkiHQobR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0IowBChxHZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEhEKCWFwaV9tYWpvchgBIAEoBRIzCgxjYXBhYmlsaXRpZXMYAiABKAsyHS5tZWNhdGwudjEuU2VydmVyQ2FwYWJpbGl0aWVzEhAKCGZlYXR1cmVzGAMgAygJEhIKCmRlcGxveW1lbnQYBCABKAkirQYKElNlcnZlckNhcGFiaWxpdGllcxILCgNtY3AYASABKAgSFgoOc2xhc2hfY29tbWFuZHMYAiABKAgSDgoGbWVtb3J5GAMgASgIEg4KBnNraWxscxgEIAEoCBINCgV0ZWFtcxgFIAEoCBINCgVzaGVsbBgGIAEoCBINCgVpbWFnZRgHIAEoCBINCgVhdWRpbxgIIAEoCBIOCgZhZ2VudHMYCSABKAgSDAoEc291bBgKIAEoCBISCgp1c2VyX21vZGVsGAsgASgIEhcKD21vZGVsX3NlbGVjdGlvbhgMIAEoCBIPCgdwb3N0dXJlGA0gASgJEhEKCXdvcmt0cmVlcxgOIAEoCBISCgpzY2hlZHVsaW5nGA8gASgIEhIKCnJlZmxlY3Rpb24YECABKAgSGgoSbGVhcm5pbmdfcHJvcG9zYWxzGBEgASgIEhYKDmxlYXJuZWRfc2tpbGxzGBIgASgIEhcKD3N0b3JhZ2VfY2xlYW51cBgWIAEoCBI4CgxtYW51YWxfZHJlYW0YEyABKAsyIi5tZWNhdGwudjEuTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSFgoOc3RvcmFnZV9oZWFsdGgYFyABKAgSDQoFc3RlZXIYGCABKAgSGQoRbWFudWFsX2NvbXBhY3Rpb24YGSABKAgSFQoNc2Vzc2lvbl9kZWJ1ZxgaIAEoCBIRCglkZWJ1Z19tY3AYGyABKAgSHAoUd29ya3NwYWNlX2Vucm9sbG1lbnQYHCABKAgSHAoUbWNwX2Nvbm5lY3Rvcl9zdGF0dXMYHSABKAgSEwoLbWNwX3JlZnJlc2gYHiABKAgSGwoTZXhlY3V0aW9uX3RlbXBsYXRlcxgfIAEoCBIcCg9wcm9qZWN0X3RydXN0ZWQYICABKAhIAIgBARIiChVzdWJhZ2VudF9hc2tfcmV2aWV3ZXIYISABKAlIAYgBAUISChBfcHJvamVjdF90cnVzdGVkQhgKFl9zdWJhZ2VudF9hc2tfcmV2aWV3ZXJKBAgUEBVKBAgVEBZSD2xlZ2FjeV9hZG9wdGlvblIRc3RvcmFnZV9taWdyYXRpb24iNQofTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJIrIBCiBMaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXNwb25zZRIUCgxhdmFpbGFiaWxpdHkYASABKAkSGAoQZW5yb2xsbWVudF9zdGF0ZRgCIAEoCRIxCgpjb25uZWN0b3JzGAMgAygLMh0ubWVjYXRsLnYxLk1jcENvbm5lY3RvclN0YXR1cxIYChB0b3RhbF9jb25uZWN0b3JzGAQgASgNEhEKCXRydW5jYXRlZBgFIAEoCCJPChJNY3BDb25uZWN0b3JTdGF0dXMSDAoEbmFtZRgBIAEoCRIXCg9jYXRhbG9ndWVfc3RhdGUYAiABKAkSEgoKdG9vbF9jb3VudBgDIAEoDSKIAgoVQ3JlYXRlU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSPAoUc2Vzc2lvbl9jYXBhYmlsaXRpZXMYAyABKAsyHi5tZWNhdGwudjEuU2Vzc2lvbkNhcGFiaWxpdGllcxIwCg5yZXNvbHZlZF9tb2RlbBgEIAEoCzIYLm1lY2F0bC52MS5SZXNvbHZlZE1vZGVsEi8KCXBsYWNlbWVudBgFIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YRImCh5yZXNvbHZlZF9hZ2VudF9kZWZpbml0aW9uX25hbWUYBiABKAlKBAgCEANSDGNhcGFiaWxpdGllcyJSChFQbGFjZW1lbnRNZXRhZGF0YRIMCgRraW5kGAEgASgJEg0KBWxhYmVsGAIgASgJEg4KBmJyYW5jaBgDIAEoCRIQCghyZXZpc2lvbhgEIAEoCSJoCg1SZXNvbHZlZE1vZGVsEhMKC3Byb3ZpZGVyX2lkGAEgASgJEhAKCG1vZGVsX2lkGAIgASgJEhYKDmNvbnRleHRfd2luZG93GAMgASgDEhgKEHJlYXNvbmluZ19lZmZvcnQYBCABKAkiZAoTU2Vzc2lvbkNhcGFiaWxpdGllcxINCgVpbWFnZRgBIAEoCBINCgVhdWRpbxgCIAEoCBIXCg9leGVjdXRpb25fZmlsZXMYAyABKAgSFgoOYnVpbHRfaW5fc2hlbGwYBCABKAgiMAoRR2V0U2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI5ChJHZXRTZXNzaW9uUmVzcG9uc2USIwoHc2Vzc2lvbhgBIAEoCzISLm1lY2F0bC52MS5TZXNzaW9uIjoKG0dldFNlc3Npb25UcmFuc2NyaXB0UmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIlIKFEFjdGl2aXR5UmVwbGF5U3RhdHVzEhEKCWF2YWlsYWJsZRgBIAEoCBIQCghjb21wbGV0ZRgCIAEoCBIVCg1hdXRob3JpdGF0aXZlGAMgASgIIu0BChxHZXRTZXNzaW9uVHJhbnNjcmlwdFJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSMAoIbWVzc2FnZXMYAiADKAsyHi5tZWNhdGwudjEuQ29udmVyc2F0aW9uTWVzc2FnZRIQCghjb21wbGV0ZRgDIAEoCBIxCghhY3Rpdml0eRgEIAEoCzIfLm1lY2F0bC52MS5BY3Rpdml0eVJlcGxheVN0YXR1cxIMCgRraW5kGAUgASgJEjQKDHJlbGF0aW9uc2hpcBgGIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uUmVsYXRpb25zaGlwIjkKGlN0cmVhbVNlc3Npb25FdmVudHNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiNwoYU3RyZWFtU2Vzc2lvbkxpdmVSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiWAoZV2F0Y2hTZXNzaW9uRXZlbnRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEg4KBmN1cnNvchgCIAEoCRIOCgZydW5faWQYAyABKAkiXAoaV2F0Y2hTZXNzaW9uRXZlbnRzUmVzcG9uc2USHwoFZXZlbnQYASABKAsyEC5tZWNhdGwudjEuRXZlbnQSDgoGY3Vyc29yGAIgASgJEg0KBXBoYXNlGAMgASgJIjgKE0xpc3RTZXNzaW9uc1JlcXVlc3QSEQoJcGFnZV9zaXplGAEgASgFEg4KBmN1cnNvchgCIAEoCSJOCglQcmluY2lwYWwSDgoGaXNzdWVyGAEgASgJEg8KB3N1YmplY3QYAiABKAkSEgoKZ3JhbnRfdHlwZRgDIAEoCRIMCgRuYW1lGAQgASgJIv4ECg5TZXNzaW9uU3VtbWFyeRISCgpzZXNzaW9uX2lkGAEgASgJEhgKEG1vZGlmaWVkX2F0X3VuaXgYAiABKAMSDQoFc3RhdGUYAyABKAkSDQoFdHVybnMYBCABKAUSEAoIbW9kZWxfaWQYBSABKAkSFwoPY3JlYXRlZF9hdF91bml4GAYgASgDEiMKBW93bmVyGAggASgLMhQubWVjYXRsLnYxLlByaW5jaXBhbBIMCgRraW5kGAkgASgJEjQKDHJlbGF0aW9uc2hpcBgKIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uUmVsYXRpb25zaGlwEj0KDGNhcGFiaWxpdGllcxgLIAEoCzInLm1lY2F0bC52MS5TZXNzaW9uSW52ZW50b3J5Q2FwYWJpbGl0aWVzEhMKC3JlYXNvbl9jb2RlGAwgASgJEi8KCXBsYWNlbWVudBgPIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YRIvCg50aXRsZV9tZXRhZGF0YRgQIAEoCzIXLm1lY2F0bC52MS5TZXNzaW9uVGl0bGUSPgoLdG9rZW5fdXNhZ2UYESADKAsyKS5tZWNhdGwudjEuU2Vzc2lvblN1bW1hcnkuVG9rZW5Vc2FnZUVudHJ5EhYKDmFjdGl2aXR5X3N0YXRlGBIgASgJGkgKD1Rva2VuVXNhZ2VFbnRyeRILCgNrZXkYASABKAkSJAoFdmFsdWUYAiABKAsyFS5tZWNhdGwudjEuVG9rZW5Vc2FnZToCOAFKBAgHEAhKBAgNEA5KBAgOEA9SBXRpdGxlUgl3b3Jrc3BhY2VSEHRpdGxlX3Byb3ZlbmFuY2Ui5gEKE1Nlc3Npb25SZWxhdGlvbnNoaXASGQoRcGFyZW50X3Nlc3Npb25faWQYASABKAkSDwoHY2FsbF9pZBgCIAEoCRIZCgxicmFuY2hfaW5kZXgYAyABKAVIAIgBARIVCg1zY2hlZHVsZV9uYW1lGAQgASgJEhkKEW9yaWdpbl9zZXNzaW9uX2lkGAUgASgJEg8KB3RlYW1faWQYBiABKAkSEwoLbWVtYmVyX25hbWUYByABKAkSHwoXZGVidWdfdGFyZ2V0X3Nlc3Npb25faWQYCCABKAlCDwoNX2JyYW5jaF9pbmRleCKSAgocU2Vzc2lvbkludmVudG9yeUNhcGFiaWxpdGllcxITCgtwdWJsaWNfY2hhdBgBIAEoCBIPCgdpbnNwZWN0GAIgASgIEiAKGGF1dGhvcml0YXRpdmVfdHJhbnNjcmlwdBgDIAEoCBIXCg9hY3Rpdml0eV9yZXBsYXkYBCABKAgSDwoHY29weV9pZBgFIAEoCBIXCg92aWV3X3RyYW5zY3JpcHQYBiABKAgSDAoEZm9yaxgHIAEoCBIOCgZyZW5hbWUYCCABKAgSDgoGZGVsZXRlGAkgASgIEjkKB3JlYXNvbnMYCiABKAsyKC5tZWNhdGwudjEuU2Vzc2lvbkludmVudG9yeUFjdGlvblJlYXNvbnMinQEKHVNlc3Npb25JbnZlbnRvcnlBY3Rpb25SZWFzb25zEhMKC3B1YmxpY19jaGF0GAEgASgJEg8KB2luc3BlY3QYAiABKAkSDwoHY29weV9pZBgDIAEoCRIXCg92aWV3X3RyYW5zY3JpcHQYBCABKAkSDAoEZm9yaxgFIAEoCRIOCgZyZW5hbWUYBiABKAkSDgoGZGVsZXRlGAcgASgJIm0KFExpc3RTZXNzaW9uc1Jlc3BvbnNlEisKCHNlc3Npb25zGAEgAygLMhkubWVjYXRsLnYxLlNlc3Npb25TdW1tYXJ5EhMKC25leHRfY3Vyc29yGAIgASgJEhMKC3RvdGFsX2NvdW50GAMgASgFIhkKF0dldFN0b3JhZ2VIZWFsdGhSZXF1ZXN0It4BCg9SZXRlbnRpb25Qb2xpY3kSHAoUbWFpbl9tYXhfYWdlX3NlY29uZHMYASABKAMSFgoObWFpbl9tYXhfY291bnQYAiABKAUSHQoVY2hpbGRfbWF4X2FnZV9zZWNvbmRzGAMgASgDEhcKD2NoaWxkX21heF9jb3VudBgEIAEoBRIhChlzY2hlZHVsZWRfbWF4X2FnZV9zZWNvbmRzGAUgASgDEhsKE3NjaGVkdWxlZF9tYXhfY291bnQYBiABKAUSHQoVc3dlZXBfY2FkZW5jZV9zZWNvbmRzGAcgASgDIskHChhHZXRTdG9yYWdlSGVhbHRoUmVzcG9uc2USEQoJYXZhaWxhYmxlGAEgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgCIAEoCRIVCg1jdXJyZW50X2J5dGVzGAMgASgDEh8KF2N1cnJlbnRfYnl0ZXNfYXZhaWxhYmxlGAQgASgIEhkKEXJlY2xhaW1hYmxlX2J5dGVzGAUgASgDEiMKG3JlY2xhaW1hYmxlX2J5dGVzX2F2YWlsYWJsZRgGIAEoCBIVCg1zZXNzaW9uX2NvdW50GAcgASgDEhIKCmZpbGVfY291bnQYCCABKAMSEAoIdjFfY291bnQYCSABKAMSEAoIdjJfY291bnQYCiABKAMSEgoKbWFpbl9jb3VudBgLIAEoAxITCgtjaGlsZF9jb3VudBgMIAEoAxIXCg9zY2hlZHVsZWRfY291bnQYDSABKAMSFQoNdW5rbm93bl9jb3VudBgOIAEoAxIVCg1jb3JydXB0X2NvdW50GA8gASgDEioKBnBvbGljeRgQIAEoCzIaLm1lY2F0bC52MS5SZXRlbnRpb25Qb2xpY3kSFwoPbGFzdF9zd2VlcF91bml4GBEgASgDEhwKFGxhc3Rfc3dlZXBfYXZhaWxhYmxlGBIgASgIEhcKD25leHRfc3dlZXBfdW5peBgTIAEoAxIcChRuZXh0X3N3ZWVwX2F2YWlsYWJsZRgUIAEoCBISCgphY3RpdmVfam9iGBUgASgJEhQKDGxhc3RfZmFpbHVyZRgWIAEoCRIkChxvd25lcmxlc3Nfc2Vzc2lvbnNfYXZhaWxhYmxlGBcgASgIEi0KJW93bmVybGVzc19zZXNzaW9uc191bmF2YWlsYWJsZV9yZWFzb24YGCABKAkSHwoXb3duZXJsZXNzX3Nlc3Npb25fY291bnQYGSABKAMSHQoVb3duZXJsZXNzX3Nlc3Npb25faWRzGBogAygJEicKH293bmVybGVzc19zZXNzaW9uX2lkc190cnVuY2F0ZWQYGyABKAgSJQodb3duZXJsZXNzX3NjaGVkdWxlc19hdmFpbGFibGUYHCABKAgSLgomb3duZXJsZXNzX3NjaGVkdWxlc191bmF2YWlsYWJsZV9yZWFzb24YHSABKAkSIAoYb3duZXJsZXNzX3NjaGVkdWxlX2NvdW50GB4gASgDEiAKGG93bmVybGVzc19zY2hlZHVsZV9uYW1lcxgfIAMoCRIqCiJvd25lcmxlc3Nfc2NoZWR1bGVfbmFtZXNfdHJ1bmNhdGVkGCAgASgIItkCCg1DbGVhbnVwQ291bnRzEg0KBXRvdGFsGAEgASgFEjUKB2J5X2tpbmQYAiADKAsyJC5tZWNhdGwudjEuQ2xlYW51cENvdW50cy5CeUtpbmRFbnRyeRI3CghieV9zdGF0ZRgDIAMoCzIlLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5U3RhdGVFbnRyeRI5CglieV9yZWFzb24YBCADKAsyJi5tZWNhdGwudjEuQ2xlYW51cENvdW50cy5CeVJlYXNvbkVudHJ5Gi0KC0J5S2luZEVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEaLgoMQnlTdGF0ZUVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEaLwoNQnlSZWFzb25FbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAU6AjgBIoYBChBDbGVhbnVwQ2FuZGlkYXRlEhIKCnNlc3Npb25faWQYASABKAkSDAoEa2luZBgCIAEoCRINCgVzdGF0ZRgDIAEoCRIOCgZyZWFzb24YBCABKAkSGAoQbW9kaWZpZWRfYXRfdW5peBgFIAEoAxIXCg9lc3RpbWF0ZWRfYnl0ZXMYBiABKAMiKgoZUGxhblNlc3Npb25DbGVhbnVwUmVxdWVzdBINCgVraW5kcxgBIAMoCSLTAgoaUGxhblNlc3Npb25DbGVhbnVwUmVzcG9uc2USGgoSY29uZmlybWF0aW9uX3Rva2VuGAEgASgJEhEKCWF2YWlsYWJsZRgCIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAyABKAkSEgoKZ2VuZXJhdGlvbhgEIAEoCRIWCg5wb2xpY3lfdmVyc2lvbhgFIAEoCRItCghlbGlnaWJsZRgGIAMoCzIbLm1lY2F0bC52MS5DbGVhbnVwQ2FuZGlkYXRlEisKCXByb3RlY3RlZBgHIAEoCzIYLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzEhcKD2VzdGltYXRlZF9ieXRlcxgIIAEoAxIWCg5wbGFubmVkX2pvYl9pZBgJIAEoCRIxCg9lbGlnaWJsZV9jb3VudHMYCiABKAsyGC5tZWNhdGwudjEuQ2xlYW51cENvdW50cyJBChpBcHBseVNlc3Npb25DbGVhbnVwUmVxdWVzdBIjChJjb25maXJtYXRpb25fdG9rZW4YASABKAlCB7pIBHICEAEiNgobQ2FuY2VsU2Vzc2lvbkNsZWFudXBSZXF1ZXN0EhcKBmpvYl9pZBgBIAEoCUIHukgEcgIQASI2ChtHZXRTZXNzaW9uQ2xlYW51cEpvYlJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIk0KEENsZWFudXBJdGVtRXJyb3ISEwoLaXRlbV9oYW5kbGUYASABKAkSEwoLcmVhc29uX2NvZGUYAiABKAkSDwoHbWVzc2FnZRgDIAEoCSKsAQoKQ2xlYW51cEpvYhIOCgZqb2JfaWQYASABKAkSDQoFc3RhdGUYAiABKAkSEQoJcHJvY2Vzc2VkGAMgASgFEg8KB2RlbGV0ZWQYBCABKAUSDwoHc2tpcHBlZBgFIAEoBRINCgVzdGFsZRgGIAEoBRIOCgZmYWlsZWQYByABKAUSKwoGZXJyb3JzGAggAygLMhsubWVjYXRsLnYxLkNsZWFudXBJdGVtRXJyb3IiVgoOU2V0TW9kZVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlIjYKD1NldE1vZGVSZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iMgoTQ2xvc2VTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIhYKFENsb3NlU2Vzc2lvblJlc3BvbnNlIksKFFJlbmFtZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESFgoFdGl0bGUYAiABKAlCB7pIBHICEAEiPAoVUmVuYW1lU2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiIzChREZWxldGVTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIhcKFURlbGV0ZVNlc3Npb25SZXNwb25zZSJvChNDbGVhclNlc3Npb25SZXF1ZXN0EiIKEXNvdXJjZV9zZXNzaW9uX2lkGAEgASgJQge6SARyAhABEh4KEXdvcmt0cmVlX3NlbGVjdG9yGAIgASgJSACIAQFCFAoSX3dvcmt0cmVlX3NlbGVjdG9yIlsKFENsZWFyU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSLwoJcGxhY2VtZW50GAIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIr4BChJGb3JrU2Vzc2lvblJlcXVlc3QSIgoRc291cmNlX3Nlc3Npb25faWQYASABKAlCB7pIBHICEAESDQoFdGl0bGUYAiABKAkSGAoQcmVhc29uaW5nX2VmZm9ydBgDIAEoCRIeChF3b3JrdHJlZV9zZWxlY3RvchgEIAEoCUgAiAEBEhMKC3Byb3ZpZGVyX2lkGAUgASgJEhAKCG1vZGVsX2lkGAYgASgJQhQKEl93b3JrdHJlZV9zZWxlY3RvciJaChNGb3JrU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSLwoJcGxhY2VtZW50GAIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIjsKEENvbnRleHRPY2N1cGFuY3kSFAoMaW5wdXRfdG9rZW5zGAEgASgDEhEKCWVzdGltYXRlZBgCIAEoCCKsBgoHU2Vzc2lvbhISCgpzZXNzaW9uX2lkGAEgASgJEg0KBXN0YXRlGAIgASgJEicKBG1vZGUYAyABKA4yGS5tZWNhdGwudjEuUGVybWlzc2lvbk1vZGUSIQoGbGltaXRzGAUgASgLMhEubWVjYXRsLnYxLkxpbWl0cxINCgV0dXJucxgGIAEoBRISCgp0b29sX2NhbGxzGAcgASgFEhcKD2NyZWF0ZWRfYXRfdW5peBgIIAEoAxIwCg5yZXNvbHZlZF9tb2RlbBgJIAEoCzIYLm1lY2F0bC52MS5SZXNvbHZlZE1vZGVsEgwKBGtpbmQYDiABKAkSNAoMcmVsYXRpb25zaGlwGA8gASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXASGQoRZGVidWdfbWNwX3NlcnZlcnMYECADKAkSFwoPZGVidWdfbWNwX3Rvb2xzGBEgAygJEi8KCXBsYWNlbWVudBgSIAEoCzIcLm1lY2F0bC52MS5QbGFjZW1lbnRNZXRhZGF0YRIvCg50aXRsZV9tZXRhZGF0YRgTIAEoCzIXLm1lY2F0bC52MS5TZXNzaW9uVGl0bGUSNwoLdG9rZW5fdXNhZ2UYFCADKAsyIi5tZWNhdGwudjEuU2Vzc2lvbi5Ub2tlblVzYWdlRW50cnkSPAoUc2Vzc2lvbl9jYXBhYmlsaXRpZXMYFSABKAsyHi5tZWNhdGwudjEuU2Vzc2lvbkNhcGFiaWxpdGllcxI9ChhsYXRlc3RfY29udGV4dF9vY2N1cGFuY3kYFiABKAsyGy5tZWNhdGwudjEuQ29udGV4dE9jY3VwYW5jeRpICg9Ub2tlblVzYWdlRW50cnkSCwoDa2V5GAEgASgJEiQKBXZhbHVlGAIgASgLMhUubWVjYXRsLnYxLlRva2VuVXNhZ2U6AjgBSgQIBBAFSgQIChALSgQICxAMSgQIDBANSgQIDRAOUgl3b3Jrc3BhY2VSBXRpdGxlUgxjYXBhYmlsaXRpZXNSEHRpdGxlX3Byb3ZlbmFuY2VSGmFkb3B0aW9uX3NvdXJjZV9zZXNzaW9uX2lkIpUBCgxTZXNzaW9uVGl0bGUSDQoFdGl0bGUYASABKAkSEgoKcHJvdmVuYW5jZRgCIAEoCRIYChBnZW5lcmF0aW9uX3N0YXRlGAMgASgJEjYKDmxhdGVzdF9hdHRlbXB0GAQgASgLMh4ubWVjYXRsLnYxLlRpdGxlQXR0ZW1wdFN1bW1hcnkSEAoIcmV2aXNpb24YBSABKAQiOAoTVGl0bGVBdHRlbXB0U3VtbWFyeRIKCgJpZBgBIAEoCRIPCgdvdXRjb21lGAIgASgJSgQIAxAEIqEBCgpUb2tlblVzYWdlEh8KBXRvdGFsGAEgASgLMhAubWVjYXRsLnYxLlVzYWdlEjEKBm1vZGVscxgCIAMoCzIhLm1lY2F0bC52MS5Ub2tlblVzYWdlLk1vZGVsc0VudHJ5Gj8KC01vZGVsc0VudHJ5EgsKA2tleRgBIAEoCRIfCgV2YWx1ZRgCIAEoCzIQLm1lY2F0bC52MS5Vc2FnZToCOAEixAIKD0NvbnZlcnNlUmVxdWVzdBIjCgZwcm9tcHQYASABKAsyES5tZWNhdGwudjEuUHJvbXB0SAASJgoFcmV0cnkYAiABKAsyFS5tZWNhdGwudjEuUmV0cnlTdGFydEgAEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIABIuCgxjYW5jZWxfY2hpbGQYDCABKAsyFi5tZWNhdGwudjEuQ2FuY2VsQ2hpbGRIABIhCgVzdGVlchgNIAEoCzIQLm1lY2F0bC52MS5TdGVlckgAEi4KDHN0ZWVyX2NhbmNlbBgOIAEoCzIWLm1lY2F0bC52MS5TdGVlckNhbmNlbEgAQgYKBGtpbmQiMwoQQ29udmVyc2VSZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKcAQoHQ29udGVudBIlCgRraW5kGAEgASgOMhcubWVjYXRsLnYxLkNvbnRlbnQuS2luZBIRCgltaW1lX3R5cGUYAiABKAkSDAoEZGF0YRgDIAEoDBILCgN1cmwYBCABKAkiPAoES2luZBIUChBLSU5EX1VOU1BFQ0lGSUVEEAASDgoKS0lORF9JTUFHRRABEg4KCktJTkRfQVVESU8QAiKQAwoMQ29udGVudEJsb2NrEioKBGtpbmQYASABKA4yHC5tZWNhdGwudjEuQ29udGVudEJsb2NrLktpbmQSEQoJbWltZV90eXBlGAIgASgJEgwKBGRhdGEYAyABKAwSCwoDdXJsGAQgASgJEgwKBHRleHQYBSABKAkSDAoEbmFtZRgGIAEoCRINCgV0aXRsZRgHIAEoCRITCgtkZXNjcmlwdGlvbhgIIAEoCRIMCgRzaXplGAkgASgDEhAKCGF1ZGllbmNlGAogAygJEhAKCHByaW9yaXR5GAsgASgBEhUKDWxhc3RfbW9kaWZpZWQYDCABKAkinAEKBEtpbmQSFAoQS0lORF9VTlNQRUNJRklFRBAAEg0KCUtJTkRfVEVYVBABEg4KCktJTkRfSU1BR0UQAhIOCgpLSU5EX0FVRElPEAMSFgoSS0lORF9SRVNPVVJDRV9MSU5LEAQSGgoWS0lORF9FTUJFRERFRF9SRVNPVVJDRRAFEhsKF0tJTkRfU1RSVUNUVVJFRF9DT05URU5UEAYiKQoKUmV0cnlTdGFydBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIn4KBlByb21wdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEgwKBHRleHQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudBImCh5zZXJ2ZXJfb3duZWRfcGxhbl9jb250aW51YXRpb24YBCABKAgi1wEKDlJlc3VtZUFwcHJvdmFsEhcKBmFza19pZBgBIAEoCUIHukgEcgIQARI5Cgd2ZXJkaWN0GAMgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdEIMukgJggEGGAEYAhgDEhcKD2V4cGVjdGVkX3J1bl9pZBgEIAEoCRIRCglyZXZpZXdfaWQYBSABKAkSOAoOZ3VhcmRyYWlsX2tpbmQYBiABKA4yIC5tZWNhdGwudjEuR3VhcmRyYWlsQXBwcm92YWxLaW5kSgQIAhADUgVhbGxvdyIhCgZDYW5jZWwSFwoPZXhwZWN0ZWRfcnVuX2lkGAEgASgJIigKC0NhbmNlbENoaWxkEhkKCGNoaWxkX2lkGAEgASgJQge6SARyAhABImUKBVN0ZWVyEgwKBHRleHQYASABKAkSEgoKbWVzc2FnZV9pZBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50EhcKD2V4cGVjdGVkX3J1bl9pZBgEIAEoCSI6CgtTdGVlckNhbmNlbBISCgptZXNzYWdlX2lkGAEgASgJEhcKD2V4cGVjdGVkX3J1bl9pZBgCIAEoCSL2AQoUUmVzb2x2ZVJ1bkFza1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIgCg9leHBlY3RlZF9ydW5faWQYAiABKAlCB7pIBHICEAESFwoGYXNrX2lkGAMgASgJQge6SARyAhABEjkKB3ZlcmRpY3QYBCABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Qgy6SAmCAQYYARgCGAMSEQoJcmV2aWV3X2lkGAUgASgJEjgKDmd1YXJkcmFpbF9raW5kGAYgASgOMiAubWVjYXRsLnYxLkd1YXJkcmFpbEFwcHJvdmFsS2luZCI3ChVSZXNvbHZlUnVuQXNrUmVzcG9uc2USDgoGcnVuX2lkGAEgASgJEg4KBmFza19pZBgCIAEoCSKqAQoVUmVzb2x2ZVBsYW5Bc2tSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIAoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJQge6SARyAhABEhcKBmFza19pZBgDIAEoCUIHukgEcgIQARI5Cgd2ZXJkaWN0GAQgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdEIMukgJggEGGAEYAhgDIjgKFlJlc29sdmVQbGFuQXNrUmVzcG9uc2USDgoGcnVuX2lkGAEgASgJEg4KBmFza19pZBgCIAEoCSJRChBDYW5jZWxSdW5SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIAoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJQge6SARyAhABIiMKEUNhbmNlbFJ1blJlc3BvbnNlEg4KBnJ1bl9pZBgBIAEoCSKQAgoPU3RlZXJSdW5SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIAoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJQge6SARyAhABEgwKBHRleHQYAyABKAkSKwoFcGFydHMYBCADKAsyEi5tZWNhdGwudjEuQ29udGVudEIIukgFkgECEBASGwoKbWVzc2FnZV9pZBgFIAEoCUIHukgEcgIYQDpmukhjGmEKEXN0ZWVyX3J1bi5jb250ZW50EiN0ZXh0IGFuZCBwYXJ0cyBjYW5ub3QgYm90aCBiZSBlbXB0eRondGhpcy50ZXh0ICE9ICcnIHx8IHNpemUodGhpcy5wYXJ0cykgPiAwImAKEFN0ZWVyUnVuUmVzcG9uc2USKAoHb3V0Y29tZRgBIAEoDjIXLm1lY2F0bC52MS5TdGVlck91dGNvbWUSDgoGcnVuX2lkGAIgASgJEhIKCm1lc3NhZ2VfaWQYAyABKAkicwoVQ2FuY2VsUnVuU3RlZXJSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESIAoPZXhwZWN0ZWRfcnVuX2lkGAIgASgJQge6SARyAhABEhsKCm1lc3NhZ2VfaWQYAyABKAlCB7pIBHICGEAiZgoWQ2FuY2VsUnVuU3RlZXJSZXNwb25zZRIoCgdvdXRjb21lGAEgASgOMhcubWVjYXRsLnYxLlN0ZWVyT3V0Y29tZRIOCgZydW5faWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCSJoCiZHZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEiEKEGF1dGhvcml6YXRpb25faWQYAiABKAlCB7pIBHICEAEiNgonR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlc3BvbnNlEgsKA3VybBgBIAEoCSK0AQoeUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSGAoQYXV0aG9yaXphdGlvbl9pZBgCIAEoCRI0Cg9yZXN1bWVfYXBwcm92YWwYCiABKAsyGS5tZWNhdGwudjEuUmVzdW1lQXBwcm92YWxIABIjCgZjYW5jZWwYCyABKAsyES5tZWNhdGwudjEuQ2FuY2VsSABCCQoHY29udHJvbCJCCh9SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IrMBCh1DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhgKEGF1dGhvcml6YXRpb25faWQYAiABKAkSNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAQgkKB2NvbnRyb2wiQQoeQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IpABCg1BdXRob3JpemF0aW9uEhgKEGF1dGhvcml6YXRpb25faWQYASABKAkSDwoHY2FsbF9pZBgCIAEoCRIuCgpleHBpcmVzX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIOCgZzdGF0dXMYBCABKAkSFAoMZGlzcGxheV9uYW1lGAUgASgJIj4KF1BsYW5Db250aW51YXRpb25GYWlsdXJlEhMKC3BsYW5fcnVuX2lkGAEgASgJEg4KBmFza19pZBgCIAEoCSK3BwoFRXZlbnQSDAoEdHlwZRgBIAEoCRILCgNzZXEYAiABKAMSDAoEdHVybhgDIAEoBRIMCgR0ZXh0GAQgASgJEiYKCXRvb2xfY2FsbBgFIAEoCzITLm1lY2F0bC52MS5Ub29sQ2FsbBIqCgt0b29sX3Jlc3VsdBgGIAEoCzIVLm1lY2F0bC52MS5Ub29sUmVzdWx0EiUKA2FzaxgHIAEoCzIYLm1lY2F0bC52MS5QZXJtaXNzaW9uQXNrEiEKBnJlc3VsdBgIIAEoCzIRLm1lY2F0bC52MS5SZXN1bHQSJAoIdHVybl9lbmQYCiABKAsyEi5tZWNhdGwudjEuVHVybkVuZBIdCgRob29rGAsgASgLMg8ubWVjYXRsLnYxLkhvb2sSJQoIc3ViYWdlbnQYDCABKAsyEy5tZWNhdGwudjEuU3ViYWdlbnQSHQoEdGVhbRgNIAEoCzIPLm1lY2F0bC52MS5UZWFtEiUKCHBhcmFsbGVsGA4gASgLMhMubWVjYXRsLnYxLlBhcmFsbGVsEiwKCHNjaGVkdWxlGA8gASgLMhoubWVjYXRsLnYxLlNjaGVkdWxlUGF5bG9hZBIlCghhcHByb3ZhbBgQIAEoCzITLm1lY2F0bC52MS5BcHByb3ZhbBIqCgt1c2VyX3Byb21wdBgRIAEoCzIVLm1lY2F0bC52MS5Vc2VyUHJvbXB0EjgKEmNvbXBhY3Rpb25fYXJjaGl2ZRgSIAEoCzIcLm1lY2F0bC52MS5Db21wYWN0aW9uQXJjaGl2ZRIjCgVzdGVlchgTIAEoCzIULm1lY2F0bC52MS5TdGVlckVjaG8SKgoNc3RlZXJfb3V0Y29tZRgUIAEoCzITLm1lY2F0bC52MS5TdGVlckFjaxIqCgttb2RlbF9yZXRyeRgVIAEoCzIVLm1lY2F0bC52MS5Nb2RlbFJldHJ5Eg4KBnJ1bl9pZBgWIAEoCRImCgV0aXRsZRgXIAEoCzIXLm1lY2F0bC52MS5TZXNzaW9uVGl0bGUSLwoNYXV0aG9yaXphdGlvbhgYIAEoCzIYLm1lY2F0bC52MS5BdXRob3JpemF0aW9uEjIKD2NvbnRyb2xfcmVmdXNlZBgZIAEoCzIZLm1lY2F0bC52MS5Db250cm9sUmVmdXNlZBJFChlwbGFuX2NvbnRpbnVhdGlvbl9mYWlsdXJlGBogASgLMiIubWVjYXRsLnYxLlBsYW5Db250aW51YXRpb25GYWlsdXJlSgQICRAKUgV1c2FnZSIyCg5Db250cm9sUmVmdXNlZBIOCgZhc2tfaWQYASABKAkSEAoIY2F0ZWdvcnkYAiABKAkieAoKTW9kZWxSZXRyeRI2ChFyZXRyeV9kaXNwb3NpdGlvbhgBIAEoDjIbLm1lY2F0bC52MS5SZXRyeURpc3Bvc2l0aW9uEjIKD3N0cmVhbV9wcm9ncmVzcxgCIAEoDjIZLm1lY2F0bC52MS5TdHJlYW1Qcm9ncmVzcyJQCglTdGVlckVjaG8SDAoEdGV4dBgBIAEoCRISCgptZXNzYWdlX2lkGAIgASgJEiEKBXBhcnRzGAMgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQiaAoIU3RlZXJBY2sSKAoHb3V0Y29tZRgBIAEoDjIXLm1lY2F0bC52MS5TdGVlck91dGNvbWUSDAoEdGV4dBgCIAEoCRIQCghwcm9tb3RlZBgDIAEoCBISCgptZXNzYWdlX2lkGAQgASgJIi0KDEd1YXJkcmFpbFJlZhILCgNyZWYYASABKAkSEAoIY2F0ZWdvcnkYAiABKAkirwMKD0d1YXJkcmFpbFJldmlldxIRCglyZXZpZXdfaWQYASABKAkSJAoDam9iGAIgASgOMhcubWVjYXRsLnYxLkd1YXJkcmFpbEpvYhIyCgphc3Nlc3NtZW50GAMgASgOMh4ubWVjYXRsLnYxLkd1YXJkcmFpbEFzc2Vzc21lbnQSMgoKaW5zcGVjdGlvbhgEIAEoDjIeLm1lY2F0bC52MS5HdWFyZHJhaWxJbnNwZWN0aW9uEjQKC2Rpc3Bvc2l0aW9uGAUgASgOMh8ubWVjYXRsLnYxLkd1YXJkcmFpbERpc3Bvc2l0aW9uEhMKC3JlYXNvbl9jb2RlGAYgASgJEg8KB3J1bGVfaWQYByABKAkSEwoLcnVsZV9vcmlnaW4YCCABKAkSGwoTY2hlY2tlcl9wcm92aWRlcl9pZBgJIAEoCRIYChBjaGVja2VyX21vZGVsX2lkGAogASgJEikKCGNvbmNlcm5zGAsgAygLMhcubWVjYXRsLnYxLkd1YXJkcmFpbFJlZhIoCgdzb3VyY2VzGAwgAygLMhcubWVjYXRsLnYxLkd1YXJkcmFpbFJlZiKnAQoWR3VhcmRyYWlsQXBwcm92YWxTY29wZRIRCglyZXZpZXdfaWQYASABKAkSLgoEa2luZBgCIAEoDjIgLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbEtpbmQSFAoMZ3JhbnRfZGlnZXN0GAMgASgJEhQKDHNlc3Npb25fb25seRgEIAEoCBIYChByZXBlYXRfYXZhaWxhYmxlGAUgASgISgQIBhAHIjIKHExpc3RHdWFyZHJhaWxDb3ZlcmFnZVJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCSLTAQoWR3VhcmRyYWlsQ292ZXJhZ2VFbnRyeRIMCgR0b29sGAEgASgJEg0KBXBoYXNlGAIgASgJEiQKA2pvYhgDIAEoDjIXLm1lY2F0bC52MS5HdWFyZHJhaWxKb2ISDAoEbW9kZRgEIAEoCRIPCgdydWxlX2lkGAUgASgJEhMKC3J1bGVfb3JpZ2luGAYgASgJEjIKCmluc3BlY3Rpb24YByABKA4yHi5tZWNhdGwudjEuR3VhcmRyYWlsSW5zcGVjdGlvbhIOCgZyZWFzb24YCCABKAkimwEKHUxpc3RHdWFyZHJhaWxDb3ZlcmFnZVJlc3BvbnNlEg8KB2VuYWJsZWQYASABKAgSGwoTY2hlY2tlcl9wcm92aWRlcl9pZBgCIAEoCRIYChBjaGVja2VyX21vZGVsX2lkGAMgASgJEjIKB2VudHJpZXMYBCADKAsyIS5tZWNhdGwudjEuR3VhcmRyYWlsQ292ZXJhZ2VFbnRyeSJICh9HZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSEQoJcmV2aWV3X2lkGAIgASgJInMKIEdldEd1YXJkcmFpbFJldmlld0RldGFpbFJlc3BvbnNlEhEKCXJldmlld19pZBgBIAEoCRIPCgdjb25jZXJuGAIgASgJEhYKDnNvdXJjZV9kaXNwbGF5GAMgASgJEhMKC25leHRfYWN0aW9uGAQgASgJIpABCghBcHByb3ZhbBIOCgZhc2tfaWQYASABKAkSDAoEdG9vbBgDIAEoCRIPCgdjYWxsX2lkGAQgASgJEisKB3ZlcmRpY3QYBiABKA4yGi5tZWNhdGwudjEuQXBwcm92YWxWZXJkaWN0Eg4KBm9yaWdpbhgHIAEoCUoECAIQA0oECAUQBlIMYWxsb3dfYWx3YXlzIlAKClVzZXJQcm9tcHQSDAoEdGV4dBgBIAEoCRIhCgVwYXJ0cxgCIAMoCzISLm1lY2F0bC52MS5Db250ZW50EhEKCXN5bnRoZXRpYxgDIAEoCCJFChFDb21wYWN0aW9uQXJjaGl2ZRIwCghyZXBsYWNlZBgBIAMoCzIeLm1lY2F0bC52MS5Db252ZXJzYXRpb25NZXNzYWdlIu8BChNDb252ZXJzYXRpb25NZXNzYWdlEgwKBHJvbGUYASABKAkSDAoEdGV4dBgCIAEoCRInCgp0b29sX2NhbGxzGAMgAygLMhMubWVjYXRsLnYxLlRvb2xDYWxsEioKC3Rvb2xfcmVzdWx0GAQgASgLMhUubWVjYXRsLnYxLlRvb2xSZXN1bHQSEQoJcmVhc29uaW5nGAUgASgJEhYKDnByb3ZpZGVyX3BoYXNlGAYgASgJEiEKBXBhcnRzGAcgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSGQoRcmVhc29uaW5nX2l0ZW1faWQYCCABKAkidgoPU2NoZWR1bGVQYXlsb2FkEhUKDXNjaGVkdWxlX25hbWUYASABKAkSDwoHZmlyZV9pZBgCIAEoCRISCgpzZXNzaW9uX2lkGAMgASgJEgwKBGtpbmQYBCABKAkSDAoEc3RvcBgFIAEoCRILCgNlcnIYBiABKAkijgEKBEhvb2sSDQoFcGhhc2UYASABKAkSDAoEdG9vbBgCIAEoCRIpCghkZWNpc2lvbhgDIAEoDjIXLm1lY2F0bC52MS5Ib29rRGVjaXNpb24SDwoHY2FsbF9pZBgEIAEoCRItCglndWFyZHJhaWwYBSABKAsyGi5tZWNhdGwudjEuR3VhcmRyYWlsUmV2aWV3IqgCCg9Sb3V0aW5nRGVjaXNpb24SDwoHYmFja2VuZBgBIAEoCRIYChBjbGFzc2lmaWVyX21vZGVsGAIgASgJEhoKEmNhbmRpZGF0ZV9jYXRlZ29yeRgDIAEoCRIXCg9jYW5kaWRhdGVfbW9kZWwYBCABKAkSFwoKY29uZmlkZW5jZRgFIAEoAUgAiAEBEh8KEm1pbmltdW1fY29uZmlkZW5jZRgGIAEoAUgBiAEBEg8KB291dGNvbWUYByABKAkSGgoSY29uc2VjdXRpdmVfbWlzc2VzGAggASgFEhIKCm1pc3NfbGltaXQYCSABKAUSFAoMYnJlYWtlcl9vcGVuGAogASgIQg0KC19jb25maWRlbmNlQhUKE19taW5pbXVtX2NvbmZpZGVuY2UiigQKCFN1YmFnZW50EhYKDnBhcmVudF9jYWxsX2lkGAEgASgJEhAKCGNoaWxkX2lkGAIgASgJEgwKBGdvYWwYAyABKAkSEQoJdG9vbF9uYW1lGAQgASgJEhAKCGlzX2Vycm9yGAUgASgIEhIKCnRvb2xfY291bnQYBiABKAUSHwoFdXNhZ2UYByABKAsyEC5tZWNhdGwudjEuVXNhZ2USDAoEc3RvcBgIIAEoCRITCgtkdXJhdGlvbl9tcxgJIAEoAxISCgpiYWNrZ3JvdW5kGAogASgIEhcKD3JvdXRlZF9jYXRlZ29yeRgLIAEoCRIUCgxyb3V0ZWRfbW9kZWwYDCABKAkSDQoFbW9kZWwYDSABKAkSEgoKaW5uZXJfa2luZBgOIAEoCRIMCgR0ZXh0GA8gASgJEg4KBmRldGFpbBgQIAEoCRINCgVjYXVzZRgRIAEoCRIWCg5yb3V0aW5nX3JlYXNvbhgSIAEoCRI5ChByb3V0aW5nX2RlY2lzaW9uGBMgASgLMhoubWVjYXRsLnYxLlJvdXRpbmdEZWNpc2lvbkgAiAEBEhoKEmNoaWxkX3Rvb2xfY2FsbF9pZBgUIAEoCRIQCghwcm92aWRlchgVIAEoCRIgChhleHBsaWNpdF9yb3V0ZXJfY2F0ZWdvcnkYFiABKAlCEwoRX3JvdXRpbmdfZGVjaXNpb24ipgIKDlRlYW1NZW1iZXJTcGVjEgwKBG5hbWUYASABKAkSDAoEcm9sZRgCIAEoCRIQCghtdXRhdGluZxgDIAEoCBIMCgRsZWFkGAQgASgIEhcKD3JvdXRlZF9jYXRlZ29yeRgFIAEoCRIUCgxyb3V0ZWRfbW9kZWwYBiABKAkSDQoFbW9kZWwYByABKAkSFgoOcm91dGluZ19yZWFzb24YCCABKAkSOQoQcm91dGluZ19kZWNpc2lvbhgJIAEoCzIaLm1lY2F0bC52MS5Sb3V0aW5nRGVjaXNpb25IAIgBARIQCghwcm92aWRlchgKIAEoCRIgChhleHBsaWNpdF9yb3V0ZXJfY2F0ZWdvcnkYCyABKAlCEwoRX3JvdXRpbmdfZGVjaXNpb24i+gMKBFRlYW0SFgoOcGFyZW50X2NhbGxfaWQYASABKAkSDwoHdGVhbV9pZBgCIAEoCRIpCgZyb3N0ZXIYAyADKAsyGS5tZWNhdGwudjEuVGVhbU1lbWJlclNwZWMSDgoGbWVtYmVyGAQgASgJEhIKCmlubmVyX2tpbmQYBSABKAkSDAoEdGV4dBgGIAEoCRIRCgl0b29sX25hbWUYByABKAkSDgoGZGV0YWlsGAggASgJEhAKCGlzX2Vycm9yGAkgASgIEg4KBnJvdW5kcxgKIAEoBRIMCgRzdG9wGAsgASgJEh8KBXVzYWdlGAwgASgLMhAubWVjYXRsLnYxLlVzYWdlEhQKDGNvbnRleHRfdXNlZBgNIAEoAxIWCg5jb250ZXh0X3dpbmRvdxgOIAEoAxIiCgV0YXNrcxgPIAMoCzITLm1lY2F0bC52MS5UZWFtVGFzaxIoCghmaW5kaW5ncxgQIAMoCzIWLm1lY2F0bC52MS5UZWFtRmluZGluZxI2CgxkaXNwb3NpdGlvbnMYESADKAsyIC5tZWNhdGwudjEuVGVhbU1lbWJlckRpc3Bvc2l0aW9uEhkKEW1lbWJlcl9zZXNzaW9uX2lkGBIgASgJEg0KBWNhdXNlGBMgASgJEhoKEmNoaWxkX3Rvb2xfY2FsbF9pZBgUIAEoCSKOBQoIUGFyYWxsZWwSFgoOcGFyZW50X2NhbGxfaWQYASABKAkSDAoEa2luZBgCIAEoCRIMCgRqb2luGAMgASgJEhQKDGJyYW5jaF9jb3VudBgEIAEoBRIUCgxicmFuY2hfaW5kZXgYBSABKAUSFAoMYnJhbmNoX2xhYmVsGAYgASgJEgwKBGdvYWwYByABKAkSEQoJdG9vbF9uYW1lGAggASgJEhAKCGlzX2Vycm9yGAkgASgIEhIKCnRvb2xfY291bnQYCiABKAUSDgoGZmFpbGVkGAsgASgIEgwKBHN0b3AYDSABKAkSHwoFdXNhZ2UYDiABKAsyEC5tZWNhdGwudjEuVXNhZ2USEwoLZHVyYXRpb25fbXMYDyABKAMSDgoGd2lubmVyGBAgASgFEhAKCGNoaWxkX2lkGBIgASgJEhcKD3JvdXRlZF9jYXRlZ29yeRgTIAEoCRIUCgxyb3V0ZWRfbW9kZWwYFCABKAkSDQoFbW9kZWwYFSABKAkSEgoKaW5uZXJfa2luZBgWIAEoCRIMCgR0ZXh0GBcgASgJEg4KBmRldGFpbBgYIAEoCRIWCg5yb3V0aW5nX3JlYXNvbhgZIAEoCRI5ChByb3V0aW5nX2RlY2lzaW9uGBogASgLMhoubWVjYXRsLnYxLlJvdXRpbmdEZWNpc2lvbkgAiAEBEhoKEmNoaWxkX3Rvb2xfY2FsbF9pZBgbIAEoCRIQCghwcm92aWRlchgcIAEoCRIgChhleHBsaWNpdF9yb3V0ZXJfY2F0ZWdvcnkYHSABKAlCEwoRX3JvdXRpbmdfZGVjaXNpb25KBAgMEA1KBAgREBJSCXdvcmtzcGFjZVIQd2lubmVyX3dvcmtzcGFjZSIyCghUb29sQ2FsbBIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEgwKBGFyZ3MYAyABKAkihQEKClRvb2xSZXN1bHQSDwoHY2FsbF9pZBgBIAEoCRIPCgdjb250ZW50GAIgASgJEhAKCGlzX2Vycm9yGAMgASgIEicKBmJsb2NrcxgEIAMoCzIXLm1lY2F0bC52MS5Db250ZW50QmxvY2sSGgoSc3RydWN0dXJlZF9jb250ZW50GAUgASgJIqMBCg1QZXJtaXNzaW9uQXNrEg4KBmFza19pZBgBIAEoCRIMCgR0b29sGAIgASgJEgwKBGFyZ3MYAyABKAkSDgoGcmVhc29uGAQgASgJEjQKCWd1YXJkcmFpbBgFIAEoCzIhLm1lY2F0bC52MS5HdWFyZHJhaWxBcHByb3ZhbFNjb3BlEhQKB2NhbGxfaWQYBiABKAlIAIgBAUIKCghfY2FsbF9pZCKFAgoGUmVzdWx0EgwKBHN0b3AYASABKAkSDAoEdGV4dBgCIAEoCRIfCgV1c2FnZRgDIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRINCgVlcnJvchgEIAEoCRI7ChFyZXRyeV9kaXNwb3NpdGlvbhgGIAEoDjIbLm1lY2F0bC52MS5SZXRyeURpc3Bvc2l0aW9uSACIAQESNwoPc3RyZWFtX3Byb2dyZXNzGAcgASgOMhkubWVjYXRsLnYxLlN0cmVhbVByb2dyZXNzSAGIAQFCFAoSX3JldHJ5X2Rpc3Bvc2l0aW9uQhIKEF9zdHJlYW1fcHJvZ3Jlc3NKBAgFEAZSCXBlcm1hbmVudCJSCgdUdXJuRW5kEh8KBXVzYWdlGAEgASgLMhAubWVjYXRsLnYxLlVzYWdlEhMKC2R1cmF0aW9uX21zGAIgASgDEhEKCWVzdGltYXRlZBgDIAEoCCKFAQoFVXNhZ2USFAoMaW5wdXRfdG9rZW5zGAEgASgDEhUKDW91dHB1dF90b2tlbnMYAiABKAMSGQoRY2FjaGVfcmVhZF90b2tlbnMYAyABKAMSGgoSY2FjaGVfd3JpdGVfdG9rZW5zGAQgASgDEhgKEHJlYXNvbmluZ190b2tlbnMYBSABKAMikAEKC01jcFJlc291cmNlEg4KBnNlcnZlchgBIAEoCRILCgN1cmkYAiABKAkSDAoEbmFtZRgDIAEoCRINCgV0aXRsZRgEIAEoCRITCgtkZXNjcmlwdGlvbhgFIAEoCRIRCgltaW1lX3R5cGUYBiABKAkSDAoEc2l6ZRgHIAEoAxIRCglyZWFkX29ubHkYCCABKAgiKQoXTGlzdE1jcFJlc291cmNlc1JlcXVlc3QSDgoGc2VydmVyGAEgASgJIkUKGExpc3RNY3BSZXNvdXJjZXNSZXNwb25zZRIpCglyZXNvdXJjZXMYASADKAsyFi5tZWNhdGwudjEuTWNwUmVzb3VyY2UiUQoTTWNwUmVzb3VyY2VDb250ZW50cxILCgN1cmkYASABKAkSEQoJbWltZV90eXBlGAIgASgJEgwKBHRleHQYAyABKAkSDAoEYmxvYhgEIAEoDCJHChZSZWFkTWNwUmVzb3VyY2VSZXF1ZXN0EhcKBnNlcnZlchgBIAEoCUIHukgEcgIQARIUCgN1cmkYAiABKAlCB7pIBHICEAEiSwoXUmVhZE1jcFJlc291cmNlUmVzcG9uc2USMAoIY29udGVudHMYASADKAsyHi5tZWNhdGwudjEuTWNwUmVzb3VyY2VDb250ZW50cyJXChFNY3BQcm9tcHRBcmd1bWVudBIMCgRuYW1lGAEgASgJEg0KBXRpdGxlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEhAKCHJlcXVpcmVkGAQgASgIIn4KCU1jcFByb21wdBIOCgZzZXJ2ZXIYASABKAkSDAoEbmFtZRgCIAEoCRINCgV0aXRsZRgDIAEoCRITCgtkZXNjcmlwdGlvbhgEIAEoCRIvCglhcmd1bWVudHMYBSADKAsyHC5tZWNhdGwudjEuTWNwUHJvbXB0QXJndW1lbnQiJwoVTGlzdE1jcFByb21wdHNSZXF1ZXN0Eg4KBnNlcnZlchgBIAEoCSI/ChZMaXN0TWNwUHJvbXB0c1Jlc3BvbnNlEiUKB3Byb21wdHMYASADKAsyFC5tZWNhdGwudjEuTWNwUHJvbXB0IrkBChNHZXRNY3BQcm9tcHRSZXF1ZXN0EhcKBnNlcnZlchgBIAEoCUIHukgEcgIQARIVCgRuYW1lGAIgASgJQge6SARyAhABEkAKCWFyZ3VtZW50cxgDIAMoCzItLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXF1ZXN0LkFyZ3VtZW50c0VudHJ5GjAKDkFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiLgoQTWNwUHJvbXB0TWVzc2FnZRIMCgRyb2xlGAEgASgJEgwKBHRleHQYAiABKAkiWgoUR2V0TWNwUHJvbXB0UmVzcG9uc2USEwoLZGVzY3JpcHRpb24YASABKAkSLQoIbWVzc2FnZXMYAiADKAsyGy5tZWNhdGwudjEuTWNwUHJvbXB0TWVzc2FnZSJMCg1NY3BTZXJ2ZXJJbmZvEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEhEKCXRyYW5zcG9ydBgDIAEoCRINCgVncm91cBgEIAEoCSKHAQoJTWNwU291cmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCRIPCgdlbmFibGVkGAMgASgIEg0KBWdyb3VwGAQgASgJEikKB3NlcnZlcnMYBSADKAsyGC5tZWNhdGwudjEuTWNwU2VydmVySW5mbxITCgtkaWFnbm9zdGljcxgGIAMoCSIXChVMaXN0TWNwU291cmNlc1JlcXVlc3QidQoWTGlzdE1jcFNvdXJjZXNSZXNwb25zZRIlCgdzb3VyY2VzGAEgAygLMhQubWVjYXRsLnYxLk1jcFNvdXJjZRIQCghyZXZpc2lvbhgCIAEoBBINCgVzdGFsZRgDIAEoCBITCgtyZWNvbmNpbGluZxgEIAEoCCI3ChhSZWZyZXNoTWNwU291cmNlc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI+ChlSZWZyZXNoTWNwU291cmNlc1Jlc3BvbnNlEhAKCHJldmlzaW9uGAEgASgEEg8KB2NoYW5nZWQYAiABKAgiGwoZTGlzdFRvb2xIaXZlR3JvdXBzUmVxdWVzdCIsChpMaXN0VG9vbEhpdmVHcm91cHNSZXNwb25zZRIOCgZncm91cHMYASADKAkidAoJQWdlbnRJbmZvEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDQoFbW9kZWwYAyABKAkSDQoFdG9vbHMYBCADKAkSFwoPcGVybWlzc2lvbl9tb2RlGAUgASgJEg0KBWNvbG9yGAYgASgJIhMKEUxpc3RBZ2VudHNSZXF1ZXN0IjoKEkxpc3RBZ2VudHNSZXNwb25zZRIkCgZhZ2VudHMYASADKAsyFC5tZWNhdGwudjEuQWdlbnRJbmZvIiwKB0NvbW1hbmQSDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCSIyChNMaXN0Q29tbWFuZHNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiPAoUTGlzdENvbW1hbmRzUmVzcG9uc2USJAoIY29tbWFuZHMYASADKAsyEi5tZWNhdGwudjEuQ29tbWFuZCJpCghXb3JrdHJlZRIQCghzZWxlY3RvchgBIAEoCRIMCgRraW5kGAIgASgJEg0KBWxhYmVsGAMgASgJEg4KBmJyYW5jaBgEIAEoCRIQCghyZXZpc2lvbhgFIAEoCRIMCgRiYXJlGAYgASgIIjMKFExpc3RXb3JrdHJlZXNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiPwoVTGlzdFdvcmt0cmVlc1Jlc3BvbnNlEiYKCXdvcmt0cmVlcxgBIAMoCzITLm1lY2F0bC52MS5Xb3JrdHJlZSJwCglTa2lsbEluZm8SDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRITCgthZ2VudF9vd25lZBgDIAEoCBITCgtvd25lcl9hZ2VudBgEIAEoCRIWCg5hY3RpdmVfdmVyc2lvbhgFIAEoCSITChFMaXN0U2tpbGxzUmVxdWVzdCI6ChJMaXN0U2tpbGxzUmVzcG9uc2USJAoGc2tpbGxzGAEgAygLMhQubWVjYXRsLnYxLlNraWxsSW5mbyJBCg1Ta2lsbEZpbGVJbmZvEgwKBG5hbWUYASABKAkSDAoEc2l6ZRgCIAEoAxIUCgxpbnN0cnVjdGlvbnMYAyABKAgiLgoVTGlzdFNraWxsRmlsZXNSZXF1ZXN0EhUKBG5hbWUYASABKAlCB7pIBHICEAEiQQoWTGlzdFNraWxsRmlsZXNSZXNwb25zZRInCgVmaWxlcxgBIAMoCzIYLm1lY2F0bC52MS5Ta2lsbEZpbGVJbmZvIkQKFFJlYWRTa2lsbEZpbGVSZXF1ZXN0EhUKBG5hbWUYASABKAlCB7pIBHICEAESFQoEZmlsZRgCIAEoCUIHukgEcgIQASIoChVSZWFkU2tpbGxGaWxlUmVzcG9uc2USDwoHY29udGVudBgBIAEoCSKhAQoIU291bEluZm8SDwoHY29udGVudBgBIAEoCRISCgpzaXplX2J5dGVzGAIgASgDEg4KBnNoYTI1NhgDIAEoCRIPCgdwcmVzZW50GAQgASgIEi0KCnByb3ZlbmFuY2UYBSABKA4yGS5tZWNhdGwudjEuU291bFByb3ZlbmFuY2USDwoHdHJ1c3RlZBgGIAEoCBIPCgdkcmlmdGVkGAcgASgIIhAKDkdldFNvdWxSZXF1ZXN0IjQKD0dldFNvdWxSZXNwb25zZRIhCgRzb3VsGAEgASgLMhMubWVjYXRsLnYxLlNvdWxJbmZvIjIKDlVzZXJNb2RlbEVudHJ5EgsKA2tleRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCSIiChNHZXRVc2VyTW9kZWxSZXF1ZXN0EgsKA2tleRgBIAEoCSKWAgoRVXNlck1vZGVsUmV2aXNpb24SCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEg8KB3ZlcnNpb24YBCABKAkSDgoGc3RhdHVzGAUgASgJEg4KBndyaXRlchgGIAEoCRIOCgZvcmlnaW4YByABKAkSGQoRc291cmNlX3Nlc3Npb25faWQYCCABKAkSGgoSc291cmNlX3Byb3Bvc2FsX2lkGAkgASgJEi4KCnVwZGF0ZWRfYXQYCyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSgQIChALUg9zb3VyY2VfZXZlbnRfaWRSEXNvdXJjZV9tZXNzYWdlX2lkIooBCg9Vc2VyTW9kZWxEZXRhaWwSLQoHY3VycmVudBgBIAEoCzIcLm1lY2F0bC52MS5Vc2VyTW9kZWxSZXZpc2lvbhItCgdoaXN0b3J5GAIgAygLMhwubWVjYXRsLnYxLlVzZXJNb2RlbFJldmlzaW9uEhkKEWhpc3RvcnlfYXZhaWxhYmxlGAMgASgIIpIBChRHZXRVc2VyTW9kZWxSZXNwb25zZRIqCgdlbnRyaWVzGAEgAygLMhkubWVjYXRsLnYxLlVzZXJNb2RlbEVudHJ5EhIKCnNpemVfYnl0ZXMYAiABKAMSDgoGc2hhMjU2GAMgASgJEioKBmRldGFpbBgEIAEoCzIaLm1lY2F0bC52MS5Vc2VyTW9kZWxEZXRhaWwikgEKCU1vZGVsSW5mbxIKCgJpZBgBIAEoCRITCgtwcm92aWRlcl9pZBgCIAEoCRIUCgxkaXNwbGF5X25hbWUYAyABKAkSDQoFaW1hZ2UYBCABKAgSEQoJcmVhc29uaW5nGAUgASgIEhUKDWNvbnRleHRfbGltaXQYBiABKAMSFQoNcHJvbXB0X2NhY2hlZBgHIAEoCCITChFMaXN0TW9kZWxzUmVxdWVzdCKbAQoOUHJvdmlkZXJTdGF0dXMSEwoLcHJvdmlkZXJfaWQYASABKAkSDQoFc3RhdGUYAiABKAkSDAoEaGludBgDIAEoCRIjChtkZWZhdWx0X21vZGVsX2F1dG9fc2VsZWN0ZWQYBCABKAgSEwoLbW9kZWxfY291bnQYBSABKAUSHQoVYXZhaWxhYmxlX25vdF9kZWZhdWx0GAYgASgIIm4KEkxpc3RNb2RlbHNSZXNwb25zZRIkCgZtb2RlbHMYASADKAsyFC5tZWNhdGwudjEuTW9kZWxJbmZvEjIKD3Byb3ZpZGVyX3N0YXR1cxgCIAMoCzIZLm1lY2F0bC52MS5Qcm92aWRlclN0YXR1cyJBChVSZWZsZWN0U2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQAUoECAIQA1IFYXN5bmMiuQEKEVJlZmxlY3Rpb25SZWNlaXB0EhUKDXJlZmxlY3Rpb25faWQYASABKAkSEwoLZGlzcG9zaXRpb24YAiABKAkSDgoGcXVldWVkGAMgASgFEhEKCWFic3RhaW5lZBgEIAEoCBIOCgZzdGFnZWQYBSABKAUSEAoIcHJvbW90ZWQYBiABKAUSEgoKY29uZmxpY3RlZBgHIAEoBRIOCgZyZWFzb24YCCABKAkSDwoHbWVzc2FnZRgJIAEoCSJHChZSZWZsZWN0U2Vzc2lvblJlc3BvbnNlEi0KB3JlY2VpcHQYASABKAsyHC5tZWNhdGwudjEuUmVmbGVjdGlvblJlY2VpcHQi8QIKD0xlYXJuaW5nQXR0ZW1wdBIKCgJpZBgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEg0KBXN0YXRlGAMgASgJEg8KB291dGNvbWUYBCABKAkSFAoMZmFpbHVyZV9jb2RlGAUgASgJEhoKEmF0dGVtcHRfZ2VuZXJhdGlvbhgGIAEoBBIYChBjbGFpbV9nZW5lcmF0aW9uGAcgASgEEjQKEGNsYWltX2V4cGlyZXNfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhgKEGNoZWNrcG9pbnRfc3RhZ2UYCSABKAkSEwoLcHJvcG9zYWxfaWQYCiABKAkSEAoIc2tpbGxfaWQYCyABKAkSLgoKY3JlYXRlZF9hdBgMIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgNIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiMAoZR2V0TGVhcm5pbmdBdHRlbXB0UmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQASJJChpHZXRMZWFybmluZ0F0dGVtcHRSZXNwb25zZRIrCgdhdHRlbXB0GAEgASgLMhoubWVjYXRsLnYxLkxlYXJuaW5nQXR0ZW1wdCJLChtMaXN0TGVhcm5pbmdBdHRlbXB0c1JlcXVlc3QSDQoFc3RhdGUYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFImEKHExpc3RMZWFybmluZ0F0dGVtcHRzUmVzcG9uc2USLAoIYXR0ZW1wdHMYASADKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0EhMKC25leHRfY3Vyc29yGAIgASgJIlYKHE11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQASJMCh1NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXNwb25zZRIrCgdhdHRlbXB0GAEgASgLMhoubWVjYXRsLnYxLkxlYXJuaW5nQXR0ZW1wdCJeChxMaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXF1ZXN0Eg4KBnN0YXR1cxgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUSDwoHcHJvamVjdBgEIAEoCSK+AQoTTGVhcm5pbmdFdmlkZW5jZVJlZhISCgpzZXNzaW9uX2lkGAEgASgJEg8KB2xvY2F0b3IYAiABKAkSDwoHb3JkaW5hbBgDIAEoBRIRCglldmVudF9zZXEYBCABKAMSFAoMdG9vbF9jYWxsX2lkGAUgASgJEg4KBmRpZ2VzdBgGIAEoCRIRCglhdmFpbGFibGUYByABKAgSFAoMYXZhaWxhYmlsaXR5GAggASgJEg8KB3ByZXZpZXcYCSABKAkiZwoQTGVhcm5pbmdEZWNpc2lvbhIMCgRraW5kGAEgASgJEg0KBWFjdG9yGAIgASgJEg4KBnJlYXNvbhgDIAEoCRImCgJhdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAieQoYTGVhcm5pbmdQcm9tb3Rpb25SZWNlaXB0EhIKCm1lbW9yeV9rZXkYASABKAkSFwoPcHJldmlvdXNfZXhpc3RzGAIgASgIEhgKEHByZXZpb3VzX3ZlcnNpb24YAyABKAkSFgoOcmVzdWx0X3ZlcnNpb24YBCABKAkinAQKEExlYXJuaW5nUHJvcG9zYWwSCgoCaWQYASABKAkSDwoHdmVyc2lvbhgCIAEoCRIOCgZzdGF0dXMYAyABKAkSDAoEa2luZBgEIAEoCRILCgNrZXkYBSABKAkSDQoFdmFsdWUYBiABKAkSEwoLZGVzY3JpcHRpb24YByABKAkSDQoFdGl0bGUYCCABKAkSDAoEYm9keRgJIAEoCRIwCghldmlkZW5jZRgKIAMoCzIeLm1lY2F0bC52MS5MZWFybmluZ0V2aWRlbmNlUmVmEhAKCHRyaWdnZXJzGAsgAygJEi4KCWRlY2lzaW9ucxgMIAMoCzIbLm1lY2F0bC52MS5MZWFybmluZ0RlY2lzaW9uEjYKCXByb21vdGlvbhgNIAEoCzIjLm1lY2F0bC52MS5MZWFybmluZ1Byb21vdGlvblJlY2VpcHQSLgoKY3JlYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASFgoOcHJvamVjdF9zY29wZWQYECABKAgSGwoTcHJvbW90aW9uX2F2YWlsYWJsZRgRIAEoCBIkChxwcm9tb3Rpb25fdW5hdmFpbGFibGVfcmVhc29uGBIgASgJEhgKEGxlYXJuZWRfc2tpbGxfaWQYEyABKAkiZAodTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVzcG9uc2USLgoJcHJvcG9zYWxzGAEgAygLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwSEwoLbmV4dF9jdXJzb3IYAiABKAkiQgoaR2V0TGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESDwoHcHJvamVjdBgCIAEoCSJMChtHZXRMZWFybmluZ1Byb3Bvc2FsUmVzcG9uc2USLQoIcHJvcG9zYWwYASABKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbCKTAQodRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQARIZCghkZWNpc2lvbhgDIAEoCUIHukgEcgIQARIOCgZyZWFzb24YBCABKAkSDwoHcHJvamVjdBgFIAEoCSJPCh5EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVzcG9uc2USLQoIcHJvcG9zYWwYASABKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbCJnChxVbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEiEKEGV4cGVjdGVkX3ZlcnNpb24YAiABKAlCB7pIBHICEAESDwoHcHJvamVjdBgDIAEoCSJOCh1VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsIuwDChNMZWFybmVkU2tpbGxWZXJzaW9uEgoKAmlkGAEgASgJEgwKBG5hbWUYAiABKAkSDwoHdmVyc2lvbhgDIAEoCRIQCghyZXZpc2lvbhgEIAEoCRINCgVzdGF0ZRgFIAEoCRITCgtvd25lcl9hZ2VudBgGIAEoCRITCgtkZXNjcmlwdGlvbhgHIAEoCRIMCgRib2R5GAggASgJEhIKCnN1cGVyc2VkZXMYCSABKAkSFgoOZXZpZGVuY2VfY291bnQYCiABKAUSMAoIZXZpZGVuY2UYCyADKAsyHi5tZWNhdGwudjEuTGVhcm5pbmdFdmlkZW5jZVJlZhIvCgtldmFsdWF0aW9ucxgMIAMoCzIaLm1lY2F0bC52MS5Ta2lsbEV2YWx1YXRpb24SLwoIcmVjZWlwdHMYDSADKAsyHS5tZWNhdGwudjEuU2tpbGxDaGFuZ2VSZWNlaXB0Ei4KCmNyZWF0ZWRfYXQYDiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhkKEWluc3BlY3RfYXZhaWxhYmxlGBAgASgIEhYKDnVuZG9fYXZhaWxhYmxlGBEgASgIIpQBCg9Ta2lsbEV2YWx1YXRpb24SDwoHdmVyZGljdBgBIAEoCRITCgtmaXh0dXJlX2lkcxgCIAMoCRIQCghiYXNlbGluZRgDIAEoCRIRCgl0cmVhdG1lbnQYBCABKAkSDgoGcmVhc29uGAUgASgJEiYKAmF0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKCAwoSU2tpbGxDaGFuZ2VSZWNlaXB0EgoKAmlkGAEgASgJEhAKCHNraWxsX2lkGAIgASgJEgwKBG5hbWUYAyABKAkSDwoHdmVyc2lvbhgEIAEoCRIRCglvcGVyYXRpb24YBSABKAkSEgoKZnJvbV9zdGF0ZRgGIAEoCRIQCgh0b19zdGF0ZRgHIAEoCRIWCg5ldmlkZW5jZV9jb3VudBgIIAEoBRIaChJzb3VyY2Vfc2Vzc2lvbl9pZHMYCSADKAkSHAoUc291cmNlX3Rvb2xfY2FsbF9pZHMYCiADKAkSDwoHdmVyZGljdBgLIAEoCRITCgtmaXh0dXJlX2lkcxgMIAMoCRIQCghiYXNlbGluZRgNIAEoCRIRCgl0cmVhdG1lbnQYDiABKAkSJgoCYXQYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhkKEWluc3BlY3RfYXZhaWxhYmxlGBAgASgIEhYKDnVuZG9fYXZhaWxhYmxlGBEgASgIIm4KGExpc3RMZWFybmVkU2tpbGxzUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBRINCgVzdGF0ZRgEIAEoCRITCgtvd25lcl9hZ2VudBgFIAEoCSKFAQoZTGlzdExlYXJuZWRTa2lsbHNSZXNwb25zZRIuCgZza2lsbHMYASADKAsyHi5tZWNhdGwudjEuTGVhcm5lZFNraWxsVmVyc2lvbhITCgtuZXh0X2N1cnNvchgCIAEoCRISCgpnZW5lcmF0aW9uGAMgASgEEg8KB3Byb2plY3QYBCABKAkibQoWR2V0TGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEg8KB3ZlcnNpb24YBCABKAkibQoXR2V0TGVhcm5lZFNraWxsUmVzcG9uc2USLQoFc2tpbGwYASABKAsyHi5tZWNhdGwudjEuTGVhcm5lZFNraWxsVmVyc2lvbhISCgpnZW5lcmF0aW9uGAIgASgEEg8KB3Byb2plY3QYAyABKAkioQEKH0RpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIdCgxmcm9tX3ZlcnNpb24YBCABKAlCB7pIBHICEAESGwoKdG9fdmVyc2lvbhgFIAEoCUIHukgEcgIQASKRAQogRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVzcG9uc2USDAoEZGlmZhgBIAEoCRISCgpnZW5lcmF0aW9uGAIgASgEEg8KB3Byb2plY3QYAyABKAkSEAoIc2tpbGxfaWQYBCABKAkSFAoMZnJvbV92ZXJzaW9uGAUgASgJEhIKCnRvX3ZlcnNpb24YBiABKAkinQEKGU11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIYCgd2ZXJzaW9uGAQgASgJQge6SARyAhABEiIKEWV4cGVjdGVkX3JldmlzaW9uGAUgASgJQge6SARyAhABIqcBChpNdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRItCgVza2lsbBgBIAEoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCRIaChJwdWJsaWNhdGlvbl9zdGF0dXMYBCABKAkSGQoRcHVibGljYXRpb25fZXJyb3IYBSABKAkipgEKG1JvbGxiYWNrTGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEh8KDnRhcmdldF92ZXJzaW9uGAQgASgJQge6SARyAhABEiIKEWV4cGVjdGVkX3JldmlzaW9uGAUgASgJQge6SARyAhABIkkKF0xpc3RTa2lsbENoYW5nZXNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFIoQBChhMaXN0U2tpbGxDaGFuZ2VzUmVzcG9uc2USLgoHY2hhbmdlcxgBIAMoCzIdLm1lY2F0bC52MS5Ta2lsbENoYW5nZVJlY2VpcHQSEwoLbmV4dF9jdXJzb3IYAiABKAkSEgoKZ2VuZXJhdGlvbhgDIAEoBBIPCgdwcm9qZWN0GAQgASgJIo8BChFDcmVhdGVUZWFtUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEgwKBG5hbWUYAiABKAkSKAoHbWVtYmVycxgDIAMoCzIXLm1lY2F0bC52MS5UZWFtbWF0ZVNwZWMSDAoEZ29hbBgEIAEoCRIXCg9tYXhfdGVhbV90b2tlbnMYBSABKAUiTQoSQ3JlYXRlVGVhbVJlc3BvbnNlEg8KB3RlYW1faWQYASABKAkSJgoHbWVtYmVycxgCIAMoCzIVLm1lY2F0bC52MS5UZWFtTWVtYmVyInEKDFRlYW1tYXRlU3BlYxIVCgRuYW1lGAEgASgJQge6SARyAhABEhIKCmFnZW50X3R5cGUYAiABKAkSDAoEbGVhZBgDIAEoCBIQCghtdXRhdGluZxgEIAEoCBIWCg5pbml0aWFsX3Byb21wdBgFIAEoCSKTAQoUU3Bhd25UZWFtbWF0ZVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQARIVCgRuYW1lGAIgASgJQge6SARyAhABEhIKCmFnZW50X3R5cGUYAyABKAkSDAoEbGVhZBgEIAEoCBIQCghtdXRhdGluZxgFIAEoCBIWCg5pbml0aWFsX3Byb21wdBgGIAEoCSI+ChVTcGF3blRlYW1tYXRlUmVzcG9uc2USJQoGbWVtYmVyGAEgASgLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXIicAoaU2VuZFRlYW1tYXRlTWVzc2FnZVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQARITCgJ0bxgCIAEoCUIHukgEcgIQARIMCgRmcm9tGAMgASgJEhUKBGJvZHkYBCABKAlCB7pIBHICEAEiHQobU2VuZFRlYW1tYXRlTWVzc2FnZVJlc3BvbnNlIkoKFUNhbmNlbFRlYW1tYXRlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhcKBm1lbWJlchgCIAEoCUIHukgEcgIQASIYChZDYW5jZWxUZWFtbWF0ZVJlc3BvbnNlIioKDlJ1blRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEiZQoJVGVhbUV2ZW50Eg4KBm1lbWJlchgBIAEoCRIfCgVldmVudBgCIAEoCzIQLm1lY2F0bC52MS5FdmVudBInCgdvdXRjb21lGAMgASgLMhYubWVjYXRsLnYxLlRlYW1PdXRjb21lItsBCgtUZWFtT3V0Y29tZRIOCgZyb3VuZHMYASABKAUSEQoJcXVpZXNjZW50GAIgASgIEhgKEGJ1ZGdldF9leGhhdXN0ZWQYAyABKAgSDAoEc3RvcBgEIAEoCRIfCgV1c2FnZRgFIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRI2CgxkaXNwb3NpdGlvbnMYBiADKAsyIC5tZWNhdGwudjEuVGVhbU1lbWJlckRpc3Bvc2l0aW9uEigKCGZpbmRpbmdzGAcgAygLMhYubWVjYXRsLnYxLlRlYW1GaW5kaW5nIisKD0xpc3RUZWFtUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABInEKEExpc3RUZWFtUmVzcG9uc2USJgoHbWVtYmVycxgBIAMoCzIVLm1lY2F0bC52MS5UZWFtTWVtYmVyEiIKBXRhc2tzGAIgAygLMhMubWVjYXRsLnYxLlRlYW1UYXNrEhEKCXF1aWVzY2VudBgDIAEoCCJRCgpUZWFtTWVtYmVyEgwKBG5hbWUYASABKAkSEgoKYWdlbnRfdHlwZRgCIAEoCRINCgVzdGF0ZRgDIAEoCRISCgpzZXNzaW9uX2lkGAQgASgJIloKCFRlYW1UYXNrEgoKAmlkGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg0KBXN0YXRlGAMgASgJEhAKCGFzc2lnbmVlGAQgASgJEgwKBGRlcHMYBSADKAkiKwoLVGVhbUZpbmRpbmcSDgoGbWVtYmVyGAEgASgJEgwKBGJvZHkYAiABKAkifQoVVGVhbU1lbWJlckRpc3Bvc2l0aW9uEgwKBG5hbWUYASABKAkSDwoHc3RvcHBlZBgCIAEoCBIvCgZyZWFzb24YAyABKA4yHy5tZWNhdGwudjEuVGVhbU1lbWJlclN0b3BSZWFzb24SFAoMZXJyb3Jfcm91bmRzGAQgASgFIi4KEkNsZWFudXBUZWFtUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABIhUKE0NsZWFudXBUZWFtUmVzcG9uc2UibwoSQXBwcm92ZVBsYW5SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESLgoLdGFyZ2V0X21vZGUYAiABKA4yGS5tZWNhdGwudjEuUGVybWlzc2lvbk1vZGUSDAoEbm90ZRgDIAEoCSKJAQoXTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSOAoOcHJvamVjdF9tZW1vcnkYASABKAsyIC5tZWNhdGwudjEuRHJlYW1UYXJnZXRDYXBhYmlsaXR5EjQKCnVzZXJfbW9kZWwYAiABKAsyIC5tZWNhdGwudjEuRHJlYW1UYXJnZXRDYXBhYmlsaXR5IlUKFURyZWFtVGFyZ2V0Q2FwYWJpbGl0eRIQCghnZW5lcmF0ZRgBIAEoCBIOCgZkZWNpZGUYAiABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAMgASgJIioKGEdlbmVyYXRlRHJlYW1QbGFuUmVxdWVzdBIOCgZ0YXJnZXQYASABKAkiRQoZR2VuZXJhdGVEcmVhbVBsYW5SZXNwb25zZRIoCgRwbGFuGAEgASgLMhoubWVjYXRsLnYxLkRyZWFtUmV2aWV3UGxhbiI7ChZEZWNpZGVEcmVhbVBsYW5SZXF1ZXN0Eg8KB3BsYW5faWQYASABKAkSEAoIZGVjaXNpb24YAiABKAkiQwoXRGVjaWRlRHJlYW1QbGFuUmVzcG9uc2USKAoHcmVjZWlwdBgBIAEoCzIXLm1lY2F0bC52MS5EcmVhbVJlY2VpcHQiywEKD0RyZWFtUmV2aWV3UGxhbhIKCgJpZBgBIAEoCRIOCgZ0YXJnZXQYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHwoXcGxhbm5lZF9vcGVyYXRpb25fY291bnQYBCABKAUSHAoUcGxhbm5lZF9zb3VyY2VfY291bnQYBSABKAUSLQoKb3BlcmF0aW9ucxgGIAMoCzIZLm1lY2F0bC52MS5EcmVhbU9wZXJhdGlvbiLfAQoORHJlYW1PcGVyYXRpb24SDAoEa2luZBgBIAEoCRItCghzdXJ2aXZvchgCIAEoCzIbLm1lY2F0bC52MS5EcmVhbVBhcnRpY2lwYW50EiwKB3NvdXJjZXMYAyADKAsyGy5tZWNhdGwudjEuRHJlYW1QYXJ0aWNpcGFudBIwCgtyZXBsYWNlbWVudBgEIAEoCzIbLm1lY2F0bC52MS5EcmVhbVJlcGxhY2VtZW50Eg4KBnJlYXNvbhgFIAEoCRIgChhleGFjdF9kdXBsaWNhdGVfZWxpZ2libGUYBiABKAgiQwoQRHJlYW1QYXJ0aWNpcGFudBILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkiNgoQRHJlYW1SZXBsYWNlbWVudBINCgV2YWx1ZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCSLXAQoMRHJlYW1SZWNlaXB0EgoKAmlkGAEgASgJEg4KBnRhcmdldBgCIAEoCRITCgtkaXNwb3NpdGlvbhgDIAEoCRIcChRwbGFubmVkX3NvdXJjZV9jb3VudBgEIAEoBRIcChRhcHBsaWVkX3NvdXJjZV9jb3VudBgFIAEoBRIfChdjb25mbGljdGVkX3NvdXJjZV9jb3VudBgGIAEoBRIcChRza2lwcGVkX3NvdXJjZV9jb3VudBgHIAEoBRIbChNmYWlsZWRfc291cmNlX2NvdW50GAggASgFIjQKFUNvbXBhY3RTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIisKFkNvbXBhY3RTZXNzaW9uUmVzcG9uc2USEQoJY29tcGFjdGVkGAEgASgIIjcKIVdvcmtzcGFjZUVucm9sbG1lbnRDb25uZWN0UmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJIk4KIVdvcmtzcGFjZUVucm9sbG1lbnRDb250cm9sUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhUKDWVucm9sbG1lbnRfaWQYAiABKAkicQoTV29ya3NwYWNlRW5yb2xsbWVudBIVCg1lbnJvbGxtZW50X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIZChFyZXF1aXJlZF9zZXJ2aWNlcxgDIAEoDRIYChBwcmVzZW50YXRpb25fdXJsGAQgASgJKr4BCg5QZXJtaXNzaW9uTW9kZRIfChtQRVJNSVNTSU9OX01PREVfVU5TUEVDSUZJRUQQABIbChdQRVJNSVNTSU9OX01PREVfREVGQVVMVBABEhgKFFBFUk1JU1NJT05fTU9ERV9QTEFOEAISIAocUEVSTUlTU0lPTl9NT0RFX0FDQ0VQVF9FRElUUxADEhgKFFBFUk1JU1NJT05fTU9ERV9BVVRPEAQSGAoUUEVSTUlTU0lPTl9NT0RFX1lPTE8QBSqSAQoPQXBwcm92YWxWZXJkaWN0EiAKHEFQUFJPVkFMX1ZFUkRJQ1RfVU5TUEVDSUZJRUQQABIZChVBUFBST1ZBTF9WRVJESUNUX0RFTlkQARIfChtBUFBST1ZBTF9WRVJESUNUX0FMTE9XX09OQ0UQAhIhCh1BUFBST1ZBTF9WRVJESUNUX0FMTE9XX0FMV0FZUxADKr4BCgxTdGVlck91dGNvbWUSHQoZU1RFRVJfT1VUQ09NRV9VTlNQRUNJRklFRBAAEhoKFlNURUVSX09VVENPTUVfQUNDRVBURUQQARIaChZTVEVFUl9PVVRDT01FX0FQUEVOREVEEAISGwoXU1RFRVJfT1VUQ09NRV9SRVRSQUNURUQQAxIeChpTVEVFUl9PVVRDT01FX05PTkVfUEVORElORxAEEhoKFlNURUVSX09VVENPTUVfVE9PX0xBVEUQBSqAAQoMR3VhcmRyYWlsSm9iEh0KGUdVQVJEUkFJTF9KT0JfVU5TUEVDSUZJRUQQABIYChRHVUFSRFJBSUxfSk9CX0FDVElPThABEhkKFUdVQVJEUkFJTF9KT0JfSU5CT1VORBACEhwKGEdVQVJEUkFJTF9KT0JfUEVSTUlTU0lPThADKqoBChNHdWFyZHJhaWxBc3Nlc3NtZW50EiQKIEdVQVJEUkFJTF9BU1NFU1NNRU5UX1VOU1BFQ0lGSUVEEAASIwofR1VBUkRSQUlMX0FTU0VTU01FTlRfQUNDRVBUQUJMRRABEiMKH0dVQVJEUkFJTF9BU1NFU1NNRU5UX1BST0hJQklURUQQAhIjCh9HVUFSRFJBSUxfQVNTRVNTTUVOVF9VTlJFU09MVkVEEAMqjAEKE0d1YXJkcmFpbEluc3BlY3Rpb24SJAogR1VBUkRSQUlMX0lOU1BFQ1RJT05fVU5TUEVDSUZJRUQQABIhCh1HVUFSRFJBSUxfSU5TUEVDVElPTl9DT01QTEVURRABEiwKKEdVQVJEUkFJTF9JTlNQRUNUSU9OX09QRVJBVElPTkFMX0ZBSUxVUkUQAirQAgoUR3VhcmRyYWlsRGlzcG9zaXRpb24SJQohR1VBUkRSQUlMX0RJU1BPU0lUSU9OX1VOU1BFQ0lGSUVEEAASIQodR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0VYRUNVVEUQARIkCiBHVUFSRFJBSUxfRElTUE9TSVRJT05fQVNLX0FDVElPThACEikKJUdVQVJEUkFJTF9ESVNQT1NJVElPTl9XSVRISE9MRF9SRVNVTFQQAxIoCiRHVUFSRFJBSUxfRElTUE9TSVRJT05fUkVMRUFTRV9SRVNVTFQQBBIeChpHVUFSRFJBSUxfRElTUE9TSVRJT05fREVOWRAFEicKI0dVQVJEUkFJTF9ESVNQT1NJVElPTl9QQVNTX0FEVklTT1JZEAYSKgomR1VBUkRSQUlMX0RJU1BPU0lUSU9OX0NPTlRJTlVFX1dBUk5JTkcQByqQAQoVR3VhcmRyYWlsQXBwcm92YWxLaW5kEicKI0dVQVJEUkFJTF9BUFBST1ZBTF9LSU5EX1VOU1BFQ0lGSUVEEAASIgoeR1VBUkRSQUlMX0FQUFJPVkFMX0tJTkRfQUNUSU9OEAESKgomR1VBUkRSQUlMX0FQUFJPVkFMX0tJTkRfUkVTVUxUX1JFTEVBU0UQAiqYAQoMSG9va0RlY2lzaW9uEh0KGUhPT0tfREVDSVNJT05fVU5TUEVDSUZJRUQQABIWChJIT09LX0RFQ0lTSU9OX0lORk8QARIZChVIT09LX0RFQ0lTSU9OX0JMT0NLRUQQAhIaChZIT09LX0RFQ0lTSU9OX01PRElGSUVEEAMSGgoWSE9PS19ERUNJU0lPTl9BRFZJU09SWRAEKpYBChBSZXRyeURpc3Bvc2l0aW9uEiEKHVJFVFJZX0RJU1BPU0lUSU9OX1VOU1BFQ0lGSUVEEAASHQoZUkVUUllfRElTUE9TSVRJT05fVU5LTk9XThABEh8KG1JFVFJZX0RJU1BPU0lUSU9OX1JFVFJZQUJMRRACEh8KG1JFVFJZX0RJU1BPU0lUSU9OX1BFUk1BTkVOVBADKqgBCg5TdHJlYW1Qcm9ncmVzcxIfChtTVFJFQU1fUFJPR1JFU1NfVU5TUEVDSUZJRUQQABIbChdTVFJFQU1fUFJPR1JFU1NfVU5LTk9XThABEh0KGVNUUkVBTV9QUk9HUkVTU19QUkVDT01NSVQQAhIbChdTVFJFQU1fUFJPR1JFU1NfVklTSUJMRRADEhwKGFNUUkVBTV9QUk9HUkVTU19DT01QTEVURRAEKoQBCg5Tb3VsUHJvdmVuYW5jZRIfChtTT1VMX1BST1ZFTkFOQ0VfVU5TUEVDSUZJRUQQABIYChRTT1VMX1BST1ZFTkFOQ0VfVVNFUhABEhsKF1NPVUxfUFJPVkVOQU5DRV9QUk9KRUNUEAISGgoWU09VTF9QUk9WRU5BTkNFX0RSSVZFUhADKq0BChRUZWFtTWVtYmVyU3RvcFJlYXNvbhInCiNURUFNX01FTUJFUl9TVE9QX1JFQVNPTl9VTlNQRUNJRklFRBAAEiEKHVRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0VSUk9SEAESJQohVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fQ0FOQ0VMTEVEEAISIgoeVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fQlVER0VUEAMynDkKDkhhcm5lc3NTZXJ2aWNlEmcKFEdldENvbXBhdGliaWxpdHlJbmZvEiYubWVjYXRsLnYxLkdldENvbXBhdGliaWxpdHlJbmZvUmVxdWVzdBonLm1lY2F0bC52MS5HZXRDb21wYXRpYmlsaXR5SW5mb1Jlc3BvbnNlEm0KFkxpc3RFeGVjdXRpb25UZW1wbGF0ZXMSKC5tZWNhdGwudjEuTGlzdEV4ZWN1dGlvblRlbXBsYXRlc1JlcXVlc3QaKS5tZWNhdGwudjEuTGlzdEV4ZWN1dGlvblRlbXBsYXRlc1Jlc3BvbnNlElIKDUNyZWF0ZVNlc3Npb24SHy5tZWNhdGwudjEuQ3JlYXRlU2Vzc2lvblJlcXVlc3QaIC5tZWNhdGwudjEuQ3JlYXRlU2Vzc2lvblJlc3BvbnNlElIKDUdldFNlcnZlckluZm8SHy5tZWNhdGwudjEuR2V0U2VydmVySW5mb1JlcXVlc3QaIC5tZWNhdGwudjEuR2V0U2VydmVySW5mb1Jlc3BvbnNlEkkKCkdldFNlc3Npb24SHC5tZWNhdGwudjEuR2V0U2Vzc2lvblJlcXVlc3QaHS5tZWNhdGwudjEuR2V0U2Vzc2lvblJlc3BvbnNlEmoKFUxpc3RHdWFyZHJhaWxDb3ZlcmFnZRInLm1lY2F0bC52MS5MaXN0R3VhcmRyYWlsQ292ZXJhZ2VSZXF1ZXN0GigubWVjYXRsLnYxLkxpc3RHdWFyZHJhaWxDb3ZlcmFnZVJlc3BvbnNlEnMKGEdldEd1YXJkcmFpbFJldmlld0RldGFpbBIqLm1lY2F0bC52MS5HZXRHdWFyZHJhaWxSZXZpZXdEZXRhaWxSZXF1ZXN0GisubWVjYXRsLnYxLkdldEd1YXJkcmFpbFJldmlld0RldGFpbFJlc3BvbnNlEmcKFEdldFNlc3Npb25UcmFuc2NyaXB0EiYubWVjYXRsLnYxLkdldFNlc3Npb25UcmFuc2NyaXB0UmVxdWVzdBonLm1lY2F0bC52MS5HZXRTZXNzaW9uVHJhbnNjcmlwdFJlc3BvbnNlEkAKB1NldE1vZGUSGS5tZWNhdGwudjEuU2V0TW9kZVJlcXVlc3QaGi5tZWNhdGwudjEuU2V0TW9kZVJlc3BvbnNlEk8KDENsb3NlU2Vzc2lvbhIeLm1lY2F0bC52MS5DbG9zZVNlc3Npb25SZXF1ZXN0Gh8ubWVjYXRsLnYxLkNsb3NlU2Vzc2lvblJlc3BvbnNlElIKDVJlbmFtZVNlc3Npb24SHy5tZWNhdGwudjEuUmVuYW1lU2Vzc2lvblJlcXVlc3QaIC5tZWNhdGwudjEuUmVuYW1lU2Vzc2lvblJlc3BvbnNlElIKDURlbGV0ZVNlc3Npb24SHy5tZWNhdGwudjEuRGVsZXRlU2Vzc2lvblJlcXVlc3QaIC5tZWNhdGwudjEuRGVsZXRlU2Vzc2lvblJlc3BvbnNlElUKDkNvbXBhY3RTZXNzaW9uEiAubWVjYXRsLnYxLkNvbXBhY3RTZXNzaW9uUmVxdWVzdBohLm1lY2F0bC52MS5Db21wYWN0U2Vzc2lvblJlc3BvbnNlEk8KDENsZWFyU2Vzc2lvbhIeLm1lY2F0bC52MS5DbGVhclNlc3Npb25SZXF1ZXN0Gh8ubWVjYXRsLnYxLkNsZWFyU2Vzc2lvblJlc3BvbnNlEkwKC0ZvcmtTZXNzaW9uEh0ubWVjYXRsLnYxLkZvcmtTZXNzaW9uUmVxdWVzdBoeLm1lY2F0bC52MS5Gb3JrU2Vzc2lvblJlc3BvbnNlEkcKCENvbnZlcnNlEhoubWVjYXRsLnYxLkNvbnZlcnNlUmVxdWVzdBobLm1lY2F0bC52MS5Db252ZXJzZVJlc3BvbnNlKAEwARJSCg1SZXNvbHZlUnVuQXNrEh8ubWVjYXRsLnYxLlJlc29sdmVSdW5Bc2tSZXF1ZXN0GiAubWVjYXRsLnYxLlJlc29sdmVSdW5Bc2tSZXNwb25zZRJVCg5SZXNvbHZlUGxhbkFzaxIgLm1lY2F0bC52MS5SZXNvbHZlUGxhbkFza1JlcXVlc3QaIS5tZWNhdGwudjEuUmVzb2x2ZVBsYW5Bc2tSZXNwb25zZRJGCglDYW5jZWxSdW4SGy5tZWNhdGwudjEuQ2FuY2VsUnVuUmVxdWVzdBocLm1lY2F0bC52MS5DYW5jZWxSdW5SZXNwb25zZRJDCghTdGVlclJ1bhIaLm1lY2F0bC52MS5TdGVlclJ1blJlcXVlc3QaGy5tZWNhdGwudjEuU3RlZXJSdW5SZXNwb25zZRJVCg5DYW5jZWxSdW5TdGVlchIgLm1lY2F0bC52MS5DYW5jZWxSdW5TdGVlclJlcXVlc3QaIS5tZWNhdGwudjEuQ2FuY2VsUnVuU3RlZXJSZXNwb25zZRJbChBMaXN0TWNwUmVzb3VyY2VzEiIubWVjYXRsLnYxLkxpc3RNY3BSZXNvdXJjZXNSZXF1ZXN0GiMubWVjYXRsLnYxLkxpc3RNY3BSZXNvdXJjZXNSZXNwb25zZRJYCg9SZWFkTWNwUmVzb3VyY2USIS5tZWNhdGwudjEuUmVhZE1jcFJlc291cmNlUmVxdWVzdBoiLm1lY2F0bC52MS5SZWFkTWNwUmVzb3VyY2VSZXNwb25zZRJVCg5MaXN0TWNwUHJvbXB0cxIgLm1lY2F0bC52MS5MaXN0TWNwUHJvbXB0c1JlcXVlc3QaIS5tZWNhdGwudjEuTGlzdE1jcFByb21wdHNSZXNwb25zZRJPCgxHZXRNY3BQcm9tcHQSHi5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVxdWVzdBofLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXNwb25zZRJVCg5MaXN0TWNwU291cmNlcxIgLm1lY2F0bC52MS5MaXN0TWNwU291cmNlc1JlcXVlc3QaIS5tZWNhdGwudjEuTGlzdE1jcFNvdXJjZXNSZXNwb25zZRJeChFSZWZyZXNoTWNwU291cmNlcxIjLm1lY2F0bC52MS5SZWZyZXNoTWNwU291cmNlc1JlcXVlc3QaJC5tZWNhdGwudjEuUmVmcmVzaE1jcFNvdXJjZXNSZXNwb25zZRJzChhMaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnMSKi5tZWNhdGwudjEuTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVxdWVzdBorLm1lY2F0bC52MS5MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXNwb25zZRJhChJMaXN0VG9vbEhpdmVHcm91cHMSJC5tZWNhdGwudjEuTGlzdFRvb2xIaXZlR3JvdXBzUmVxdWVzdBolLm1lY2F0bC52MS5MaXN0VG9vbEhpdmVHcm91cHNSZXNwb25zZRJJCgpMaXN0QWdlbnRzEhwubWVjYXRsLnYxLkxpc3RBZ2VudHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RBZ2VudHNSZXNwb25zZRJPCgxMaXN0Q29tbWFuZHMSHi5tZWNhdGwudjEuTGlzdENvbW1hbmRzUmVxdWVzdBofLm1lY2F0bC52MS5MaXN0Q29tbWFuZHNSZXNwb25zZRJSCg1MaXN0V29ya3RyZWVzEh8ubWVjYXRsLnYxLkxpc3RXb3JrdHJlZXNSZXF1ZXN0GiAubWVjYXRsLnYxLkxpc3RXb3JrdHJlZXNSZXNwb25zZRJQChNTdHJlYW1TZXNzaW9uRXZlbnRzEiUubWVjYXRsLnYxLlN0cmVhbVNlc3Npb25FdmVudHNSZXF1ZXN0GhAubWVjYXRsLnYxLkV2ZW50MAESTAoRU3RyZWFtU2Vzc2lvbkxpdmUSIy5tZWNhdGwudjEuU3RyZWFtU2Vzc2lvbkxpdmVSZXF1ZXN0GhAubWVjYXRsLnYxLkV2ZW50MAESYwoSV2F0Y2hTZXNzaW9uRXZlbnRzEiQubWVjYXRsLnYxLldhdGNoU2Vzc2lvbkV2ZW50c1JlcXVlc3QaJS5tZWNhdGwudjEuV2F0Y2hTZXNzaW9uRXZlbnRzUmVzcG9uc2UwARKIAQofR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvbhIxLm1lY2F0bC52MS5HZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uUmVxdWVzdBoyLm1lY2F0bC52MS5HZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uUmVzcG9uc2USdAoXUmVjaGVja01jcEF1dGhvcml6YXRpb24SKS5tZWNhdGwudjEuUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXF1ZXN0GioubWVjYXRsLnYxLlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVzcG9uc2UoATABEnEKFkNhbmNlbE1jcEF1dGhvcml6YXRpb24SKC5tZWNhdGwudjEuQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlcXVlc3QaKS5tZWNhdGwudjEuQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlKAEwARJPCgxMaXN0U2Vzc2lvbnMSHi5tZWNhdGwudjEuTGlzdFNlc3Npb25zUmVxdWVzdBofLm1lY2F0bC52MS5MaXN0U2Vzc2lvbnNSZXNwb25zZRJbChBHZXRTdG9yYWdlSGVhbHRoEiIubWVjYXRsLnYxLkdldFN0b3JhZ2VIZWFsdGhSZXF1ZXN0GiMubWVjYXRsLnYxLkdldFN0b3JhZ2VIZWFsdGhSZXNwb25zZRJhChJQbGFuU2Vzc2lvbkNsZWFudXASJC5tZWNhdGwudjEuUGxhblNlc3Npb25DbGVhbnVwUmVxdWVzdBolLm1lY2F0bC52MS5QbGFuU2Vzc2lvbkNsZWFudXBSZXNwb25zZRJTChNBcHBseVNlc3Npb25DbGVhbnVwEiUubWVjYXRsLnYxLkFwcGx5U2Vzc2lvbkNsZWFudXBSZXF1ZXN0GhUubWVjYXRsLnYxLkNsZWFudXBKb2ISVQoUQ2FuY2VsU2Vzc2lvbkNsZWFudXASJi5tZWNhdGwudjEuQ2FuY2VsU2Vzc2lvbkNsZWFudXBSZXF1ZXN0GhUubWVjYXRsLnYxLkNsZWFudXBKb2ISVQoUR2V0U2Vzc2lvbkNsZWFudXBKb2ISJi5tZWNhdGwudjEuR2V0U2Vzc2lvbkNsZWFudXBKb2JSZXF1ZXN0GhUubWVjYXRsLnYxLkNsZWFudXBKb2ISSQoKTGlzdFNraWxscxIcLm1lY2F0bC52MS5MaXN0U2tpbGxzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0U2tpbGxzUmVzcG9uc2USVQoOTGlzdFNraWxsRmlsZXMSIC5tZWNhdGwudjEuTGlzdFNraWxsRmlsZXNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RTa2lsbEZpbGVzUmVzcG9uc2USUgoNUmVhZFNraWxsRmlsZRIfLm1lY2F0bC52MS5SZWFkU2tpbGxGaWxlUmVxdWVzdBogLm1lY2F0bC52MS5SZWFkU2tpbGxGaWxlUmVzcG9uc2USQAoHR2V0U291bBIZLm1lY2F0bC52MS5HZXRTb3VsUmVxdWVzdBoaLm1lY2F0bC52MS5HZXRTb3VsUmVzcG9uc2USTwoMR2V0VXNlck1vZGVsEh4ubWVjYXRsLnYxLkdldFVzZXJNb2RlbFJlcXVlc3QaHy5tZWNhdGwudjEuR2V0VXNlck1vZGVsUmVzcG9uc2USVQoOUmVmbGVjdFNlc3Npb24SIC5tZWNhdGwudjEuUmVmbGVjdFNlc3Npb25SZXF1ZXN0GiEubWVjYXRsLnYxLlJlZmxlY3RTZXNzaW9uUmVzcG9uc2USYQoSR2V0TGVhcm5pbmdBdHRlbXB0EiQubWVjYXRsLnYxLkdldExlYXJuaW5nQXR0ZW1wdFJlcXVlc3QaJS5tZWNhdGwudjEuR2V0TGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USZwoUTGlzdExlYXJuaW5nQXR0ZW1wdHMSJi5tZWNhdGwudjEuTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXF1ZXN0GicubWVjYXRsLnYxLkxpc3RMZWFybmluZ0F0dGVtcHRzUmVzcG9uc2USaQoUUmV0cnlMZWFybmluZ0F0dGVtcHQSJy5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBooLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJrChZBYmFuZG9uTGVhcm5pbmdBdHRlbXB0EicubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QaKC5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USXgoRR2VuZXJhdGVEcmVhbVBsYW4SIy5tZWNhdGwudjEuR2VuZXJhdGVEcmVhbVBsYW5SZXF1ZXN0GiQubWVjYXRsLnYxLkdlbmVyYXRlRHJlYW1QbGFuUmVzcG9uc2USWAoPRGVjaWRlRHJlYW1QbGFuEiEubWVjYXRsLnYxLkRlY2lkZURyZWFtUGxhblJlcXVlc3QaIi5tZWNhdGwudjEuRGVjaWRlRHJlYW1QbGFuUmVzcG9uc2USagoVTGlzdExlYXJuaW5nUHJvcG9zYWxzEicubWVjYXRsLnYxLkxpc3RMZWFybmluZ1Byb3Bvc2Fsc1JlcXVlc3QaKC5tZWNhdGwudjEuTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVzcG9uc2USZAoTR2V0TGVhcm5pbmdQcm9wb3NhbBIlLm1lY2F0bC52MS5HZXRMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBomLm1lY2F0bC52MS5HZXRMZWFybmluZ1Byb3Bvc2FsUmVzcG9uc2USbQoWRGVjaWRlTGVhcm5pbmdQcm9wb3NhbBIoLm1lY2F0bC52MS5EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBopLm1lY2F0bC52MS5EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVzcG9uc2USagoVVW5kb0xlYXJuaW5nUHJvbW90aW9uEicubWVjYXRsLnYxLlVuZG9MZWFybmluZ1Byb21vdGlvblJlcXVlc3QaKC5tZWNhdGwudjEuVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVzcG9uc2USXgoRTGlzdExlYXJuZWRTa2lsbHMSIy5tZWNhdGwudjEuTGlzdExlYXJuZWRTa2lsbHNSZXF1ZXN0GiQubWVjYXRsLnYxLkxpc3RMZWFybmVkU2tpbGxzUmVzcG9uc2USWAoPR2V0TGVhcm5lZFNraWxsEiEubWVjYXRsLnYxLkdldExlYXJuZWRTa2lsbFJlcXVlc3QaIi5tZWNhdGwudjEuR2V0TGVhcm5lZFNraWxsUmVzcG9uc2UScwoYRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zEioubWVjYXRsLnYxLkRpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1JlcXVlc3QaKy5tZWNhdGwudjEuRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVzcG9uc2USYwoUQWN0aXZhdGVMZWFybmVkU2tpbGwSJC5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJhChJSZWplY3RMZWFybmVkU2tpbGwSJC5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJiChNBcmNoaXZlTGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USZQoUUm9sbGJhY2tMZWFybmVkU2tpbGwSJi5tZWNhdGwudjEuUm9sbGJhY2tMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlElsKEExpc3RTa2lsbENoYW5nZXMSIi5tZWNhdGwudjEuTGlzdFNraWxsQ2hhbmdlc1JlcXVlc3QaIy5tZWNhdGwudjEuTGlzdFNraWxsQ2hhbmdlc1Jlc3BvbnNlEkkKCkxpc3RNb2RlbHMSHC5tZWNhdGwudjEuTGlzdE1vZGVsc1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdE1vZGVsc1Jlc3BvbnNlEkkKCkNyZWF0ZVRlYW0SHC5tZWNhdGwudjEuQ3JlYXRlVGVhbVJlcXVlc3QaHS5tZWNhdGwudjEuQ3JlYXRlVGVhbVJlc3BvbnNlElIKDVNwYXduVGVhbW1hdGUSHy5tZWNhdGwudjEuU3Bhd25UZWFtbWF0ZVJlcXVlc3QaIC5tZWNhdGwudjEuU3Bhd25UZWFtbWF0ZVJlc3BvbnNlEmQKE1NlbmRUZWFtbWF0ZU1lc3NhZ2USJS5tZWNhdGwudjEuU2VuZFRlYW1tYXRlTWVzc2FnZVJlcXVlc3QaJi5tZWNhdGwudjEuU2VuZFRlYW1tYXRlTWVzc2FnZVJlc3BvbnNlElUKDkNhbmNlbFRlYW1tYXRlEiAubWVjYXRsLnYxLkNhbmNlbFRlYW1tYXRlUmVxdWVzdBohLm1lY2F0bC52MS5DYW5jZWxUZWFtbWF0ZVJlc3BvbnNlEjwKB1J1blRlYW0SGS5tZWNhdGwudjEuUnVuVGVhbVJlcXVlc3QaFC5tZWNhdGwudjEuVGVhbUV2ZW50MAESQwoITGlzdFRlYW0SGi5tZWNhdGwudjEuTGlzdFRlYW1SZXF1ZXN0GhsubWVjYXRsLnYxLkxpc3RUZWFtUmVzcG9uc2USTAoLQ2xlYW51cFRlYW0SHS5tZWNhdGwudjEuQ2xlYW51cFRlYW1SZXF1ZXN0Gh4ubWVjYXRsLnYxLkNsZWFudXBUZWFtUmVzcG9uc2USQAoLQXBwcm92ZVBsYW4SHS5tZWNhdGwudjEuQXBwcm92ZVBsYW5SZXF1ZXN0GhAubWVjYXRsLnYxLkV2ZW50MAESaAoYQ29ubmVjdFdvcmtzcGFjZVNlcnZpY2VzEiwubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRDb25uZWN0UmVxdWVzdBoeLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50EmgKGFJldHJ5V29ya3NwYWNlRW5yb2xsbWVudBIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudBJpChlDYW5jZWxXb3Jrc3BhY2VFbnJvbGxtZW50EiwubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRDb250cm9sUmVxdWVzdBoeLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50QqIBCg1jb20ubWVjYXRsLnYxQgxIYXJuZXNzUHJvdG9QAVo+Z2l0aHViLmNvbS9zdGFja2xvay9tZWNhdGwvY29udHJhY3RzL2dlbi9nby9tZWNhdGwvdjE7bWVjYXRsdjGiAgNNWFiqAglNZWNhdGwuVjHKAglNZWNhdGxcVjHiAhVNZWNhdGxcVjFcR1BCTWV0YWRhdGHqAgpNZWNhdGw6OlYxYgZwcm90bzM", [file_buf_validate_validate, file_google_protobuf_timestamp]); /** * Limits are the configured stop conditions for a session. A zero value in @@ -842,6 +842,18 @@ export type ServerCapabilities = Message<"mecatl.v1.ServerCapabilities"> & { * @generated from field: optional bool project_trusted = 32; */ projectTrusted?: boolean | undefined; + + /** + * subagent_ask_reviewer reports the subagent ask reviewer, a model that may + * approve a subagent's, team member's, or parallel branch's permission + * request that no human can answer: "on" (enabled), "off" (not enabled), or + * "inert" (configured, but an interactive approver answers instead). Clients + * treat other values as unknown. CHROME ONLY. Additive: an older server + * leaves it unset and the client shows nothing. + * + * @generated from field: optional string subagent_ask_reviewer = 33; + */ + subagentAskReviewer?: string | undefined; }; /** diff --git a/sdk/typescript/src/http.ts b/sdk/typescript/src/http.ts index 87de8772a9..1cb7377598 100644 --- a/sdk/typescript/src/http.ts +++ b/sdk/typescript/src/http.ts @@ -61,6 +61,10 @@ function permissionMode(value: JsonValue | undefined): string { return "plan"; case 3: return "accept_edits"; + case 4: + return "auto"; + case 5: + return "yolo"; default: return "default"; } @@ -127,7 +131,11 @@ function encodeInput( const json = record( toJson(method.input, message, { enumAsInteger: true, useProtoFieldName: true }), ); - if (method.name === "CreateSession" || method.name === "SetMode") { + if (method.name === "CreateSession" && (json.mode === undefined || json.mode === 0)) { + // An unspecified create mode is omitted so the server's configured default + // mode applies, matching gRPC. + delete json.mode; + } else if (method.name === "CreateSession" || method.name === "SetMode") { json.mode = permissionMode(json.mode); } if (method.name === "ApprovePlan" && json.target_mode !== undefined) { @@ -163,7 +171,12 @@ function permissionModeTextToNumber(value: JsonValue | undefined): number { return 2; case "accept_edits": case "acceptedits": + case "acceptEdits": return 3; + case "auto": + return 4; + case "yolo": + return 5; default: return 0; } diff --git a/sdk/typescript/src/server.ts b/sdk/typescript/src/server.ts index 8dae61a729..cdd250012a 100644 --- a/sdk/typescript/src/server.ts +++ b/sdk/typescript/src/server.ts @@ -26,6 +26,7 @@ export const ServerFeature = { ServerInfo: "server_info", SessionActivityInventory: "session_activity_inventory", SessionAgentDefinitions: "session_agent_definitions", + SessionPermissionModes: "session_permission_modes", SkillFiles: "skill_files", WatchSessionEvents: "watch_session_events", } as const; diff --git a/sdk/typescript/src/session-projections.ts b/sdk/typescript/src/session-projections.ts index b334d99156..2bf2596acf 100644 --- a/sdk/typescript/src/session-projections.ts +++ b/sdk/typescript/src/session-projections.ts @@ -26,6 +26,10 @@ export const SessionMode = { Default: 1, Plan: 2, AcceptEdits: 3, + /** Checker-approved autonomy; requires the `session_permission_modes` server feature. */ + Auto: 4, + /** Gate-free autonomy; requires the `session_permission_modes` server feature. */ + Yolo: 5, } as const; /** One SDK permission-mode value. @public */ @@ -126,6 +130,11 @@ export interface ServerCapabilities { readonly posture: string; /** Whether the server trusts its launch workspace; absent from older servers. */ readonly projectTrusted?: boolean; + /** + * Subagent ask reviewer state: `"on"`, `"off"`, or `"inert"`; treat other + * values as unknown. Absent from older servers. + */ + readonly subagentAskReviewer?: string; readonly worktrees: boolean; readonly scheduling: boolean; readonly reflection: boolean; @@ -273,6 +282,9 @@ export function projectServerCapabilities(value: ProtoServerCapabilities): Serve slashCommands: value.slashCommands, soul: value.soul, steer: value.steer, + ...(value.subagentAskReviewer === undefined + ? {} + : { subagentAskReviewer: value.subagentAskReviewer }), storageCleanup: value.storageCleanup, storageHealth: value.storageHealth, teams: value.teams, @@ -286,7 +298,9 @@ function sessionMode(value: number): SessionMode | undefined { return value === SessionMode.Unspecified || value === SessionMode.Default || value === SessionMode.Plan || - value === SessionMode.AcceptEdits + value === SessionMode.AcceptEdits || + value === SessionMode.Auto || + value === SessionMode.Yolo ? value : undefined; } diff --git a/sdk/typescript/test/package.test.ts b/sdk/typescript/test/package.test.ts index 82d5544390..951e1cde4b 100644 --- a/sdk/typescript/test/package.test.ts +++ b/sdk/typescript/test/package.test.ts @@ -630,7 +630,7 @@ test("the lifecycle surface is exported documented and API reviewed", () => { "--eval", ` import { SessionMode } from "@stacklok-oss/mecatl-sdk"; -if (JSON.stringify(SessionMode) !== JSON.stringify({ Unspecified: 0, Default: 1, Plan: 2, AcceptEdits: 3 })) { +if (JSON.stringify(SessionMode) !== JSON.stringify({ Unspecified: 0, Default: 1, Plan: 2, AcceptEdits: 3, Auto: 4, Yolo: 5 })) { throw new Error("unexpected SessionMode export"); } `, diff --git a/sdk/typescript/test/server-discovery.test.ts b/sdk/typescript/test/server-discovery.test.ts index 46a8655292..4d27a9d74c 100644 --- a/sdk/typescript/test/server-discovery.test.ts +++ b/sdk/typescript/test/server-discovery.test.ts @@ -267,6 +267,7 @@ describe("SDK server discovery", () => { ServerInfo: "server_info", SessionActivityInventory: "session_activity_inventory", SessionAgentDefinitions: "session_agent_definitions", + SessionPermissionModes: "session_permission_modes", SkillFiles: "skill_files", WatchSessionEvents: "watch_session_events", }); @@ -881,6 +882,72 @@ describe("SDK server discovery", () => { await expect(httpMalformedInfo.server.info()).rejects.toBeInstanceOf(ProtocolError); }); + it("projectTrusted stays absent when omitted and exact when present over grpc and http", async () => { + for (const projectTrusted of [undefined, true, false]) { + const grpcTransport = new DiscoveryTransport(); + const grpcResponse = { + ...validCompatibility, + capabilities: { ...completeCapabilities, projectTrusted }, + }; + grpcTransport.compatibility.push( + async () => grpcResponse, + async () => grpcResponse, + ); + const http = connect({ + baseUrl: "http://mecatl.test", + fetch: async () => + Response.json({ + api_major: 1, + capabilities: { + ...completeCapabilities, + ...(projectTrusted === undefined ? {} : { project_trusted: projectTrusted }), + }, + features: ["server_info"], + }), + }); + for (const client of [connect({ transport: grpcTransport }), http]) { + const { capabilities } = await client.server.compatibility(); + expect(capabilities.projectTrusted).toBe(projectTrusted); + expect(Object.hasOwn(capabilities, "projectTrusted")).toBe(projectTrusted !== undefined); + } + } + }); + + it("subagentAskReviewer stays absent when omitted and exact when present over grpc and http", async () => { + for (const subagentAskReviewer of [undefined, "on", "off", "inert"]) { + const grpcTransport = new DiscoveryTransport(); + const grpcResponse = { + ...validCompatibility, + capabilities: { ...completeCapabilities, subagentAskReviewer }, + }; + grpcTransport.compatibility.push( + async () => grpcResponse, + async () => grpcResponse, + ); + const http = connect({ + baseUrl: "http://mecatl.test", + fetch: async () => + Response.json({ + api_major: 1, + capabilities: { + ...completeCapabilities, + ...(subagentAskReviewer === undefined + ? {} + : { subagent_ask_reviewer: subagentAskReviewer }), + }, + features: ["server_info"], + }), + }); + for (const client of [connect({ transport: grpcTransport }), http]) { + const { capabilities } = await client.server.compatibility(); + expect(capabilities.subagentAskReviewer).toBe(subagentAskReviewer); + expect(Object.hasOwn(capabilities, "subagentAskReviewer")).toBe( + subagentAskReviewer !== undefined, + ); + } + } + }); + it("server discovery exports and api reports stay complete", () => { const typeProof: [Server, ServerCompatibility, ServerInfo, ServerInfoOptions] | undefined = undefined; @@ -928,6 +995,7 @@ describe("SDK server discovery", () => { 'readonly ServerInfo: "server_info";', 'readonly SessionActivityInventory: "session_activity_inventory";', 'readonly SessionAgentDefinitions: "session_agent_definitions";', + 'readonly SessionPermissionModes: "session_permission_modes";', 'readonly SkillFiles: "skill_files";', 'readonly WatchSessionEvents: "watch_session_events";', ]); diff --git a/sdk/typescript/test/session-lifecycle-transports.test.ts b/sdk/typescript/test/session-lifecycle-transports.test.ts index 4165f1be56..317d97ea14 100644 --- a/sdk/typescript/test/session-lifecycle-transports.test.ts +++ b/sdk/typescript/test/session-lifecycle-transports.test.ts @@ -6,6 +6,7 @@ import { type Client, connect, createHttpTransport, + ProtocolError, SESSION_ID_HEADER_NAME, ServerError, SessionMode, @@ -274,6 +275,147 @@ describe("session lifecycle transport parity", () => { await http.close(); }); + it("auto and yolo session modes round-trip over grpc", async () => { + const seenModes: number[] = []; + let stored: number = SessionMode.Unspecified; + let override: number | undefined; + const grpc = connect({ + transport: createRouterTransport((router) => { + router.service(HarnessService, { + createSession: (request) => { + seenModes.push(request.mode); + stored = request.mode; + return { sessionId: "session" }; + }, + getCompatibilityInfo: () => ({ + apiMajor: 1, + capabilities: {}, + features: ["server_info", "session_permission_modes"], + }), + getSession: (request) => ({ + session: { mode: override ?? stored, sessionId: request.sessionId }, + }), + setMode: (request) => { + seenModes.push(request.mode); + stored = request.mode; + return { session: { mode: stored, sessionId: request.sessionId } }; + }, + }); + }), + transportKind: "grpc", + }); + + const session = await grpc.sessions.create({ mode: SessionMode.Auto }); + expect((await session.snapshot()).mode).toBe(SessionMode.Auto); + expect((await (await grpc.sessions.get(session.id)).snapshot()).mode).toBe(SessionMode.Auto); + expect((await session.setMode(SessionMode.Yolo)).mode).toBe(SessionMode.Yolo); + expect((await session.snapshot()).mode).toBe(SessionMode.Yolo); + expect((await session.setMode(SessionMode.Auto)).mode).toBe(SessionMode.Auto); + expect(seenModes).toEqual([SessionMode.Auto, SessionMode.Yolo, SessionMode.Auto]); + + override = SessionMode.Yolo; + await expect(session.snapshot()).resolves.toMatchObject({ mode: SessionMode.Yolo }); + override = 6; + await expect(session.snapshot()).rejects.toBeInstanceOf(ProtocolError); + await grpc.close(); + }); + + it("auto and yolo session modes round-trip over http", async () => { + const seenModes: unknown[] = []; + // Mirrors the server's modeFromString and string(session.Mode) projection. + const canonical: Record = { + accept_edits: "acceptEdits", + auto: "auto", + default: "default", + plan: "plan", + yolo: "yolo", + }; + let stored = ""; + let override: string | undefined; + const http = connect({ + transport: createHttpTransport({ + baseUrl: "http://mecatl.test", + fetch: async (input, init) => { + const path = new URL(String(input)).pathname; + if (path === "/v1/compatibility") { + return Response.json({ + api_major: 1, + capabilities: {}, + features: ["server_info", "session_permission_modes"], + }); + } + const body = init?.body === undefined ? {} : JSON.parse(String(init.body)); + if (path === "/v1/sessions") { + seenModes.push(body.mode); + stored = canonical[body.mode] ?? ""; + return Response.json({ session_id: "session" }, { status: 201 }); + } + if (path === "/v1/sessions/session/mode") { + seenModes.push(body.mode); + stored = canonical[body.mode] ?? ""; + return Response.json({ mode: stored, session_id: "session" }); + } + if (path === "/v1/sessions/session") { + return Response.json({ mode: override ?? stored, session_id: "session" }); + } + throw new Error(`unexpected path ${path}`); + }, + }), + transportKind: "http", + }); + + const session = await http.sessions.create({ mode: SessionMode.Auto }); + expect((await session.snapshot()).mode).toBe(SessionMode.Auto); + expect((await (await http.sessions.get(session.id)).snapshot()).mode).toBe(SessionMode.Auto); + expect((await session.setMode(SessionMode.Yolo)).mode).toBe(SessionMode.Yolo); + expect((await session.snapshot()).mode).toBe(SessionMode.Yolo); + expect((await session.setMode(SessionMode.AcceptEdits)).mode).toBe(SessionMode.AcceptEdits); + expect((await session.setMode(SessionMode.Auto)).mode).toBe(SessionMode.Auto); + expect(seenModes).toEqual(["auto", "yolo", "accept_edits", "auto"]); + + override = "yolo"; + expect((await session.snapshot()).mode).toBe(SessionMode.Yolo); + override = "acceptEdits"; + expect((await session.snapshot()).mode).toBe(SessionMode.AcceptEdits); + override = ""; + expect((await session.snapshot()).mode).toBe(SessionMode.Unspecified); + await http.close(); + }); + + it("an unspecified http create omits mode so the server default applies", async () => { + const createBodies: Record[] = []; + const http = connect({ + transport: createHttpTransport({ + baseUrl: "http://mecatl.test", + fetch: async (input, init) => { + const path = new URL(String(input)).pathname; + if (path === "/v1/compatibility") { + return Response.json({ + api_major: 1, + capabilities: {}, + features: ["server_info", "session_permission_modes"], + }); + } + if (path === "/v1/sessions") { + createBodies.push(init?.body === undefined ? {} : JSON.parse(String(init.body))); + return Response.json({ session_id: "session" }, { status: 201 }); + } + if (path === "/v1/sessions/session") { + return Response.json({ mode: "yolo", session_id: "session" }); + } + throw new Error(`unexpected path ${path}`); + }, + }), + transportKind: "http", + }); + const session = await http.sessions.create({}); + await http.sessions.create({ mode: SessionMode.Default }); + expect("mode" in (createBodies[0] ?? {})).toBe(false); + expect(createBodies[1]?.mode).toBe("default"); + expect((await session.snapshot()).mode).toBe(SessionMode.Yolo); + await http.close(); + }); + it("both injected transports normalize every unary lifecycle failure class", async () => { const classes = ["projection", "snapshot-mutation", "acknowledgement", "acquisition"] as const; for (const failureClass of classes) { diff --git a/sdk/typescript/test/session-projections.test.ts b/sdk/typescript/test/session-projections.test.ts index 5ff46d3a80..837f1894d3 100644 --- a/sdk/typescript/test/session-projections.test.ts +++ b/sdk/typescript/test/session-projections.test.ts @@ -320,6 +320,7 @@ describe("session projections", () => { "slashCommands", "soul", "steer", + "subagentAskReviewer", "storageCleanup", "storageHealth", "teams", diff --git a/user-docs/building/ci/mecatequi.md b/user-docs/building/ci/mecatequi.md index c59828b3c1..f9fcb0ecfc 100644 --- a/user-docs/building/ci/mecatequi.md +++ b/user-docs/building/ci/mecatequi.md @@ -168,6 +168,12 @@ Replace `v0.0.3` with the latest released tag. The workflow preserves the three jobs and their separate permissions. Its composite action builds `mecatequi` from the tagged Mecatl source. +The workflow's `posture` input defaults to `auto`, which refuses to start +without an enforcing guardrails checker. Set `guardrails-model` to a checker +model, or set `posture: yolo` with `guardrails-model: "off"` to run without one. +Callers that relied on earlier releases running `auto` unchecked must make one +of these choices when they move to a newer tag. + Use `.github/workflows/mecatequi-example.yml` as a customizable alternative when you need a different trigger, approval stage, or author gate. @@ -246,7 +252,7 @@ corrupt both. |`--workspace`|cwd|Session workspace root. Must be a git repository top level.| |`--default-provider`|`""`|Provider ID: `openai`, `openai-codex`, `openrouter`, `anthropic`, or `opencode`.| |`--model`|`""`|Per-session passthrough model ID. Accepts any ID the provider serves, including IDs newer than the embedded catalog. Prefer this over `--default-model` for newer models.| -|`--permission-mode`|`default`|Permission mode. Use `auto` for autonomous CI, together with `--guardrails-model` or `--guardrails off`. With `default` and `--headless`, a main-agent permission ask cancels the run and exits 1. `--posture` is a deprecated alias.| +|`--permission-mode`|`default`|Permission mode. Use `auto` for autonomous CI with an enforcing guardrails checker, or `yolo` to run with no checker. With `default` and `--headless`, a main-agent permission ask cancels the run and exits 1. `--posture` is a deprecated alias.| |`--trust-project`|`false`|Trust this workspace for project content and read-only child shell access. No posture grants project trust in headless mode. Without this flag or a declared or remembered trust decision, Mecatl ignores project content such as `AGENTS.md` and does not give read-only children a shell.| |`--headless`|`true`|Controls child permission requests. The default denies them or routes them to the optional ask reviewer. See [Headless posture and permission asks](#headless-posture-and-permission-asks).| |`--timeout`|`0` (disabled)|Wall-clock bound on the whole run (for example, `40m`). A timeout-cancelled run exits 1 with `stop_reason: cancelled`.| @@ -319,16 +325,19 @@ another permission mode. Use `--permission-mode auto` for autonomous CI. It allows main-agent and child tool calls while retaining child prompt-injection defenses. It refuses to start -until you choose a guardrails checker with `--guardrails-model` or opt out with -`--guardrails off`. Reserve `yolo` for a disposable, isolated, single-tenant -environment. `trusted` and `trusted-accept-edits` also need `--trust-project` -or a declared trust decision, or the run refuses to start. +without an enforcing guardrails checker, set with `--guardrails-model` or +configured in operator settings. `yolo` runs with no checker; reserve it for a +disposable, isolated, single-tenant environment. The GitHub Action passes `--permission-mode auto` unless you set its -`permission-mode` input; its `posture` input is a deprecated alias. The action -passes `--guardrails-model` when its `guardrails-model` input is set and -`--guardrails off` when it is empty, so an action run with no checker model -runs with nothing inspecting tool content. +`permission-mode` input; its `posture` input is a deprecated alias. The +`guardrails-model` input has three choices: + +- Empty, the default: the action passes no guardrails flag, and the run uses + the checker configured in operator settings, if any. +- `off`: the action passes the `--guardrails off` kill-switch, which also + disables a checker in settings. Pair it with `permission-mode: yolo`. +- Any other value: the action passes `--guardrails-model `. For shared posture behavior, project trust, and permission-rule precedence, see [Permissions and posture](/features/security-and-execution/permissions-and-posture.md). diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index 0992ed7d78..b20970bf53 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -17,8 +17,7 @@ Configure two independent safety controls: tool arguments and results. They are independent of the permission rules. Permissions always apply. Guardrails require an operator-configured checker -model, and the allow-all permission modes require you to decide whether you -want one. +model, and the `auto` permission mode requires an enforcing one. For a custom authorization implementation, see [PermissionPolicy](/building/go/extension-points/permission-policy.md). @@ -31,6 +30,9 @@ permission configuration of the remote server. Under `mecatui connect`, the local `--permission-mode` flag accepts only `plan`, `default`, and `accept-edits`, which choose the mode of the sessions that client creates. +An ACP editor connected to `mecated acp` starts each session in the server's +default mode, and its mode picker offers only the modes the server admits. + Interactive clients such as `mecatui` can answer approval requests. For headless servers and one-shot jobs, configure the permissions required by the workload before it starts. @@ -41,21 +43,17 @@ Pass `--permission-mode` when you start `mecated`, `mecatui`, `mecak8s`, or `mecatequi`. Deny rules and configured asks win in every mode, including `yolo`. -|Mode|Project instructions and rules|Edits|Shell and other mutations|Command substitution in subagents| +|Mode|Edits|Shell and other mutations|Command substitution in subagents|Guardrails checker| |-|-|-|-|-| -|`plan`|Only with a trust source|Denied|Denied|Not applicable, read-only| -|`default`|Only with a trust source|Ask|Ask|Ask| -|`accept-edits`|Only with a trust source|Allowed|Ask|Ask| -|`trusted`|Loaded|Ask|Ask|Ask| -|`trusted-accept-edits`|Loaded|Allowed|Ask|Ask| -|`auto`|Loaded|Allowed|Allowed|Adjudicated by a reviewer model when headless| -|`yolo`|Loaded|Allowed|Allowed|Allowed| - -"Loaded" applies to an interactive root, or to a headless root that has a trust -source. See [Project trust](#project-trust) for the trust sources and -[Headless roots and project trust](#headless-roots-and-project-trust) for how -each mode behaves without one. Use `yolo` only for isolated, disposable, -single-tenant deployments. +|`plan`|Denied|Denied|Not applicable, read-only|Optional| +|`default`|Ask|Ask|Ask|Optional| +|`accept-edits`|Allowed|Ask|Ask|Optional| +|`auto`|Allowed|Allowed|Adjudicated by a reviewer model when headless|Required, enforcing| +|`yolo`|Allowed|Allowed|Allowed|Optional, advisory only| + +Whether Mecatl loads project instructions, rules, and allow rules is the +separate [project trust](#project-trust) decision; a permission mode never +grants it. Use `yolo` only for isolated, disposable, single-tenant deployments. A main-session external path can be addressed absolutely in any mode, subject to its escape permission decision. Only `yolo` also serves external relative @@ -71,7 +69,7 @@ The [`mecatequi` GitHub Action](/building/ci/mecatequi.md) also passes ```sh # Interactive: honor this project's rules and auto-accept edits. -mecatui --workspace "$PWD" --permission-mode trusted-accept-edits +mecatui --workspace "$PWD" --permission-mode accept-edits --trust-project # Unattended single-tenant deployment with a guardrails checker. mecated serve --headless --permission-mode auto --guardrails-model @@ -92,46 +90,51 @@ combines with any mode: it supplies project trust, and at `plan`, `default`, or ### What a mode sets -Each mode sets two things with different lifetimes: +Each mode sets two things: -|Mode|Posture: process-wide, fixed at startup|Session mode: where each new session starts| +|Mode|New sessions start in|Server ceiling: the most permissive mode a session may switch to| |-|-|-| -|`plan`|`strict`|`plan`| -|`default`|`strict`|`default`| -|`accept-edits`|`strict`|`accept-edits`| -|`trusted`|`trusted`|`default`| -|`trusted-accept-edits`|`trusted`|`accept-edits`| -|`auto`|`auto`|`default`| -|`yolo`|`yolo`|`default`| - -The _posture_ applies to every session the server hosts and cannot change while -the process runs. The _session mode_ is only a starting point; a client can -change it for its own session. +|`plan`|`plan`|`accept-edits`| +|`default`|`default`|`accept-edits`| +|`accept-edits`|`accept-edits`|`accept-edits`| +|`auto`|`auto`|`auto`| +|`yolo`|`yolo`|`yolo`| + +The ceiling is fixed at startup and applies to every session the server hosts. +Within it, a client can switch its own session, and the new mode takes full +effect: switching from `yolo` to `default` restores ordinary approvals. ### Change the mode after launch In `mecatui`, press `shift+tab` to cycle through every mode: **default → plan → -accept-edits → trusted → trusted-accept-edits → auto → yolo → default**. You -can remap the `ModeSwitch` action in the client keymap or with `--keymap`; see +accept-edits → auto → yolo → default**. You can remap the `ModeSwitch` action +in the client keymap or with `--keymap`; see [Keybindings](/mecatui/keybindings.md). -What happens when the cycle lands on a mode depends on the posture the server -is running: +What happens when the cycle lands on a mode depends on the server ceiling: + +- **At or below the ceiling.** The mode applies to the session immediately. +- **Above the ceiling.** The mode is unavailable until the server restarts with + a higher `--permission-mode`. The session keeps its current mode, which the + header continues to show, and you can keep typing, sending, and queueing + prompts. The footer says what the mode needs. `auto` also needs an enforcing + guardrails checker, such as `guardrails.model` in your user-global + `settings.yaml`. Press `shift+tab` again to move on. + +The server also refuses `auto` when it has no enforcing guardrails checker. The +session keeps its current mode, and the footer gives the server's reason. + +A session waiting on an approval cannot change mode. Answer the pending request +first: it resolves under the mode it was raised in, and the new mode applies +from the next run. A mode change never stops a command that has already +started. -- **Same posture.** The mode applies immediately. Under `trusted`, landing on - `trusted-accept-edits` switches the session to `accept-edits`. -- **Lower posture.** The session mode applies, but the posture stays until a - restart. If you start in `auto` and cycle to `plan`, every tool is still - allowed without asking, and the footer says so. -- **Higher posture.** The mode is blocked, because the posture is fixed when - the server starts. The header shows it as, for example, `mode auto blocked`. - The prompt area says what the mode needs: a restart, and for `auto` and - `yolo` also a guardrails checker, such as `guardrails.model` in your - user-global `settings.yaml`. While a mode is blocked you can't type, send, - or paste, and queued prompts are held. Your draft is kept. Press `esc` to go - back to the mode the session is running, or `shift+tab` to move on. +If the server restarts with a lower ceiling, or without the checker `auto` +needs, a stored session in a mode it no longer admits refuses to run, resume an +approval, fork, or clear until its owner switches it to an admitted mode. Its +history is unchanged. -The restart a posture change needs depends on how you connect: +The restart a ceiling change needs depends on how you connect: - With the embedded server, quit and relaunch `mecatui` with the new `--permission-mode` value. @@ -152,8 +155,8 @@ restart that applies to your connection. Every root logs one `permission mode` line at startup. Its fields report: - `permission_mode`: the resolved mode. -- `posture` and `session_mode`: the two values the mode set, each with a - `_scope` field stating its lifetime. +- `session_mode` and `max_allowed_mode`: where new sessions start and the + server ceiling. - `guardrails_checker`: exactly one of `enforcing`, `advisory`, or `disabled`, with a `guardrails_checker_reason` when it is not enforcing. - `subagent_ask_reviewer`: whether the @@ -170,20 +173,23 @@ warning naming the `--permission-mode` replacement, and they will be removed in a future release. Passing `--permission-mode` together with `--posture`, `--yolo`, or `--mode` is a startup error. `--trust-project` is not deprecated. -## Allow-all modes need a checker decision +## Auto needs an enforcing checker `auto` and `yolo` allow every tool without asking, which leaves a guardrails -checker as the only inspection of tool content. They refuse to start until you -make one of these choices: +checker as the only inspection of tool content. A server that starts in `auto` +refuses to start without an enforcing checker, and a session cannot be created +in or switched to `auto` without one. Configure one in either of these ways: - Set a checker with `--guardrails-model `. - Bind the `guardrail` model slot, with `--model-slot guardrail=` or `models.slots.guardrail` in `settings.yaml`. -- Run without a checker on purpose with `--guardrails off`. -The `mecak8s` Helm chart and the `mecatequi` GitHub Action always make this -choice for you: they pass the checker model you configure, or `--guardrails off` -when you leave it empty. See [Guardrails for mecak8s](/operating/mecak8s.md#choose-a-guardrails-checker) +`--guardrails off` disables any configured checker, so `auto` refuses to start +with it. To run every tool with no checker, choose `yolo`. + +The `mecak8s` Helm chart and the `mecatequi` GitHub Action pass no guardrails +flag by default, so the checker configured in settings applies. Each can also +name a checker model or pass the kill-switch. See [Guardrails for mecak8s](/operating/mecak8s.md#choose-a-guardrails-checker) and the [`mecatequi` action inputs](/building/ci/mecatequi.md#headless-posture-and-permission-asks). In a session running in `yolo` mode, a configured checker is advisory only. It @@ -195,22 +201,18 @@ or a lower mode keeps the checker enforcing. ## Headless roots and project trust -A headless root never gains project trust from its permission mode. The modes -behave differently when no trust source is present: - -- `trusted` and `trusted-accept-edits` refuse to start, because project trust is - what they add. Pass `--trust-project`, add the workspace to - `trustedWorkspaces` in your user-global `settings.yaml`, or rely on a - remembered trust decision. Otherwise choose a mode that does not name trust. -- `auto` and `yolo` start and log a warning that project instructions and rules - are withheld. Tools are still allowed without asking. -- `plan`, `default`, and `accept-edits` start without loading project content. - -On an interactive root, `trusted` and `trusted-accept-edits` grant project trust -directly. +Without a trust source, every mode starts without loading project content. +`auto` and `yolo` also log a warning that project instructions and rules are +withheld; tools are still allowed without asking. The deprecated +`--posture trusted` refuses to start on a headless root with no trust source. ## Subagents under auto +Subagents, `Parallel` branches, and team members started from an `auto` or +`yolo` session run in that same mode. A team member whose agent definition sets +`permissionMode` keeps that mode instead. Children of a `plan`, `default`, or `accept-edits` session +run in `default` mode. + Under `auto`, subagents keep the command-substitution guard that the main agent loses. A subagent Shell command containing `$(...)`, backticks, or a subshell that Mecatl cannot prove read-only is not run automatically, even though the @@ -233,6 +235,40 @@ The reviewer is separate from the guardrails checker. The checker inspects tool arguments and results; the reviewer decides pending subagent permission requests. +Clients can read the reviewer state from the server capabilities as +`subagent_ask_reviewer`: `on`, `off`, or `inert` when a reviewer is configured +but an interactive client answers the requests. An older server leaves it unset. +`mecatui`'s `/posture` shows the state when the server reports it. + +## Upgrade from the posture model + +Earlier releases fixed allow-all for the whole process with `--posture`. Allow-all +now belongs to each session's mode. This changes behavior that existing clients +and deployments can observe: + +- **Sessions created without a mode** start in the server's default mode, which + is `auto` or `yolo` on a server started that way. Previously, a gRPC session + created without a mode started in `default`. A client that cannot handle the + `auto` or `yolo` mode value in a session must pass an explicit mode. +- **An explicit `default` session gets ordinary approvals** even on a server + started with `auto` or `yolo`. Previously, such a session inherited the + process-wide allow-all. Request `auto` or `yolo` for autonomous sessions. +- **`auto` refuses to start without an enforcing checker**, including with + `--guardrails off`. A deployment that ran `--posture auto` without a checker + must configure one or choose `--permission-mode yolo`. The `mecak8s` chart + default and the `mecatequi` action default are `auto`, so they need the same + choice. +- **A mode never grants project trust.** `--permission-mode` no longer loads + project instructions and rules on interactive roots the way `--posture` did. + Pass `--trust-project` or add the workspace to `trustedWorkspaces`. +- **Stored sessions** keep their recorded mode. A session recorded in a mode the + upgraded server does not admit refuses to run until its owner switches it to + an admitted mode. + +Clients detect a server with session-scoped modes through the +`session_permission_modes` feature identifier. The API major version is +unchanged. + ## Approve and constrain work The built-in permission floor allows read-only exploration and asks before @@ -385,9 +421,10 @@ Project trust controls whether Mecatl admits project-provided authority: - the read-only child shell and workspace inspection posture. Trust can come from `--trust-project`, a `trustedWorkspaces` entry in the -user-global `settings.yaml`, an undrifted remembered trust decision, or a -`trusted`, `trusted-accept-edits`, `auto`, or `yolo` mode on an interactive -root. A headless root needs one of the first three; see +user-global `settings.yaml`, or an undrifted remembered trust decision. A +permission mode never grants trust; only the deprecated `--posture` and +`posture:` key still raise it on an interactive root. Without trust, Mecatl can +still read and search the workspace as data. See [Headless roots and project trust](#headless-roots-and-project-trust). `--trust-project` asserts that you trust the repository and its `.git` metadata. @@ -470,8 +507,8 @@ replacement actions are not supported. permission result. - `--trust-project` and permission configuration on a local `mecatui` invocation leave a remote server used through `connect` unchanged, and - `mecatui connect` refuses a `--permission-mode` that sets a posture. The - server operator owns that server's posture. + `mecatui connect` refuses `--permission-mode auto` or `yolo`. The server + operator owns that server's ceiling. ## Next steps diff --git a/user-docs/mecatui/keybindings.md b/user-docs/mecatui/keybindings.md index aa8cda4b05..401653c1bc 100644 --- a/user-docs/mecatui/keybindings.md +++ b/user-docs/mecatui/keybindings.md @@ -23,7 +23,7 @@ bindings and dims features that the connected server does not provide. |`esc`|Clear an active selection first. While work is running, cancel directly and preserve the draft, queued follow-ups, and steer. While idle with a paused queue, clear that queue but preserve the draft.| |`ctrl+t`|Open `/toolcalls` for the current session; approval requests use it for details.| |`f9`|Reveal conversation details: reasoning, turn stats, changed files, permanent error details, benign guardrail notices, and individual settled tool-call summaries. Use `ctrl+t` for tool arguments and results.| -|`shift+tab`|Cycle every permission mode: **default → plan → accept-edits → trusted → trusted-accept-edits → auto → yolo → default**. A mode that raises the posture needs a restart: it shows as blocked, prompts and edits are held, and `esc` returns to the running mode. In an MCP prompt argument form, it instead moves to the previous required field.| +|`shift+tab`|Cycle every permission mode: **default → plan → accept-edits → auto → yolo → default**. A mode above the server's ceiling keeps the current mode and your draft, and the footer says how to make it available. In an MCP prompt argument form, it instead moves to the previous required field.| |`ctrl+g`|Select all prompt text.| |`ctrl+y`|Copy the active prompt or visible conversation selection.| |`f6` / `f7` / `f8`|Open Agents / Effort / MCP Prompts.| diff --git a/user-docs/mecatui/using-the-tui.md b/user-docs/mecatui/using-the-tui.md index a6cc175c02..aff4e88def 100644 --- a/user-docs/mecatui/using-the-tui.md +++ b/user-docs/mecatui/using-the-tui.md @@ -236,11 +236,10 @@ for delegation behavior and the information available in `mecatui`. ## Change conversation settings -Press `shift+tab` to cycle through every permission mode. `default`, `plan`, -and `accept-edits` apply immediately. A mode that raises the server's posture, -such as `auto`, needs a restart. The cycle marks it blocked, holds prompts and -edits, and says what to configure and how to relaunch. Press `esc` to return -to the mode the session is running. See +Press `shift+tab` to cycle through every permission mode. A mode up to the +server's ceiling applies immediately. A mode above it keeps the session in its +current mode and leaves your draft usable, and the footer says how to relaunch +with a higher `--permission-mode`. See [Change the mode after launch](/features/security-and-execution/permissions-and-posture.md#change-the-mode-after-launch). |Command|Result| @@ -250,7 +249,7 @@ to the mode the session is running. See |`/compact`|Reduces model history while keeping the session and visible scrollback. Run it without arguments while idle. Creating a cascade summary can use model tokens.| |`/clear`|Creates an empty-history session with the same placement. It does not roll back workspace changes.| |`/session`|Shows path-free details for the active session.| -|`/posture`|Shows the server's operator posture and the independent effective checker state. Off includes setup guidance; unavailable posture status is unknown. See [Permissions and posture](/features/security-and-execution/permissions-and-posture.md).| +|`/posture`|Shows the server's operator posture, the independent effective checker state, and the subagent ask reviewer state when the server reports it. Off includes setup guidance; unavailable posture status is unknown. See [Permissions and posture](/features/security-and-execution/permissions-and-posture.md).| If `/clear` cancels an active run or approval and then fails to create the replacement, the original session remains selected and may be cancelled. Wait diff --git a/user-docs/operating/mecak8s.md b/user-docs/operating/mecak8s.md index 7dfe41c8f3..d916607a53 100644 --- a/user-docs/operating/mecak8s.md +++ b/user-docs/operating/mecak8s.md @@ -128,7 +128,7 @@ the values file if you need a fixed name. |Setting|Default| |-|-| |Replicas|Two| -|Permission mode|Headless `auto`, with no guardrails checker unless you set `guardrails.model`| +|Permission mode|Headless `auto`, which needs an enforcing guardrails checker| |Session state|Redis| |Session ownership|Kubernetes Leases| |Filesystem|No filesystem access| @@ -141,21 +141,34 @@ JSONL storage, or the `mecated` operator subcommands. ### Choose a guardrails checker -`auto` allows every tool without asking, so `mecak8s` refuses to start it until -you choose a guardrails checker or opt out. The chart always passes -`--permission-mode=auto` and declares the choice from `guardrails.model`: +`auto` allows every tool without asking, so `mecak8s` refuses to start it +without an enforcing guardrails checker. The chart renders +`--permission-mode=`, which defaults to `auto`. Configure the +checker in one of two ways: -```yaml -guardrails: - model: -``` +- Set `guardrails.model`, which renders `--guardrails-model=`: + + ```yaml + guardrails: + model: + ``` + +- Leave `guardrails.model` empty and configure the checker in mounted + settings, with a `guardrails:` model or the `guardrail` model slot. The chart + then passes no guardrails flag, and `mecak8s` uses the settings checker. + +To run every tool with no checker, set `permissionMode: yolo`. +`guardrails.disabled: true` renders the `--guardrails=off` kill-switch, which +also disables a checker in mounted settings. Setting both `guardrails.model` and +`guardrails.disabled` fails rendering. + +The chart owns the permission mode. Rendering fails if `extraArgs` contains +`--posture`, `--permission-mode`, or `--yolo`; move that choice to +`permissionMode`. `--posture=strict` becomes `permissionMode: default`. -A non-empty value renders `--guardrails-model=`. The default empty value -renders `--guardrails=off`, which runs with nothing inspecting tool content. -The kill-switch also disables a `guardrail` model slot bound in mounted -settings, so name the checker here rather than relying on a slot. When you run -the `mecak8s` binary without the chart, pass `--guardrails-model` or -`--guardrails=off` yourself. +Earlier chart versions always ran `auto` with `--guardrails=off`. Before you +upgrade such a release, configure a checker or set `permissionMode: yolo`, or +the new pods refuse to start. Because `mecak8s` is headless, the subagent ask reviewer is on by default. It uses the `ask-reviewer` model slot or the session model to decide subagent diff --git a/user-docs/operating/mecated/secure-and-expose.md b/user-docs/operating/mecated/secure-and-expose.md index 05d4977d7c..8462507c67 100644 --- a/user-docs/operating/mecated/secure-and-expose.md +++ b/user-docs/operating/mecated/secure-and-expose.md @@ -51,19 +51,20 @@ for the full behavior. ## Permission mode `--permission-mode` defaults to `default`. It accepts `plan`, `default`, -`accept-edits`, `trusted`, `trusted-accept-edits`, `auto`, or `yolo`, and it -sets the process-wide posture and the mode new sessions start in. The +`accept-edits`, `auto`, or `yolo`, and it sets the mode new sessions start in +and the server ceiling, the most permissive mode a session can switch to. The operator-global `settings.yaml` `permissionMode:` key sets the same value; the -flag overrides it. See +flag overrides it. A mode never grants project trust; pass `--trust-project` or +add the workspace to `trustedWorkspaces:`. See [Choose a permission mode](/features/security-and-execution/permissions-and-posture.md#choose-a-permission-mode) for what each mode allows. -`mecated` refuses to start in two cases: - -- `auto` or `yolo` with no guardrails checker. Pass `--guardrails-model`, bind - the `guardrail` model slot, or pass `--guardrails off`. -- `trusted` or `trusted-accept-edits` on a `--headless` root with no trust - source. Pass `--trust-project` or add the workspace to `trustedWorkspaces:`. +`mecated` refuses to start with `auto` unless an enforcing guardrails checker is +configured: pass `--guardrails-model` or bind the `guardrail` model slot. +`--guardrails off` or an advisory-only checker does not satisfy `auto`; choose +`yolo` to run without a checker. If you lower the ceiling or remove the checker, +sessions stored in a mode the server no longer admits stay intact but refuse to +run until their owner switches them to an admitted mode. On a headless root, `auto` and `yolo` start without a trust source but load no project steering and give read-only subagents no Shell, because `.git` is not diff --git a/user-docs/reference/configuration.md b/user-docs/reference/configuration.md index 55a3376fb5..598e22fbf3 100644 --- a/user-docs/reference/configuration.md +++ b/user-docs/reference/configuration.md @@ -78,11 +78,11 @@ OPERATOR-TIER LLM content-checker (issue #27). Parsed strictly. A project-tier g Tier: **operator** -OPERATOR-TIER named permission mode: plan, default, accept-edits, trusted, trusted-accept-edits, auto, or yolo. Each token sets two things: the process-wide posture, fixed at startup, and the mode new sessions start in, which each session may change. auto and yolo refuse to start without a guardrails checker unless guardrails are explicitly off. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. +OPERATOR-TIER named permission mode: plan, default, accept-edits, auto, or yolo. Each token sets two things: the mode new sessions start in, and the server ceiling, fixed at startup, which is the most permissive mode a session may switch to (accept-edits for plan, default, and accept-edits). auto refuses to start without an enforcing guardrails checker; yolo needs none. A mode never grants workspace trust. An explicit --permission-mode out-ranks this key, and it out-ranks the deprecated posture: key. A project-tier permissionMode: is IGNORED with a WARN. Empty = keep the CLI/default. | Value | Type | Default | Description | | --- | --- | --- | --- | -| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (plan/default/accept-edits/trusted/trusted-accept-edits/auto/yolo). It sets the posture and the default session mode together and supersedes the deprecated posture: key. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | +| `permissionMode` | `string` | `(empty)` | PermissionMode is the OPERATOR-TIER named permission-mode token (plan/default/accept-edits/auto/yolo). It sets the mode new sessions start in and the server ceiling (the most permissive mode a session may switch to) together, and supersedes the deprecated posture: key. It never grants workspace trust. Like Posture it is honoured ONLY from the user-global + CLI tiers; a project-tier occurrence is IGNORED with a WARN. Empty = absent. The composition layer parses the token. | ## `posture` diff --git a/user-docs/reference/grpc-schema.md b/user-docs/reference/grpc-schema.md index 66fea81a3f..bee3ea25a5 100644 --- a/user-docs/reference/grpc-schema.md +++ b/user-docs/reference/grpc-schema.md @@ -3064,6 +3064,7 @@ old clients ignore and new clients reading an old server see as false. | `mcp_refresh` | `bool` | | | mcp_refresh is true when direct/global MCP source reconciliation is wired. It is mutually exclusive with workspace_enrollment in a valid deployment. | | `execution_templates` | `bool` | | | execution_templates is true only when an authenticated template catalog is wired; an eligible inventory may still be empty. | | `project_trusted` | `bool` | optional | | project_trusted reports whether the server trusts its launch workspace's project content (rules, instructions, soul). It is an axis separate from the permission mode. CHROME ONLY. Additive: an older server leaves it unset and the client shows no trust indicator. | +| `subagent_ask_reviewer` | `string` | optional | | subagent_ask_reviewer reports the subagent ask reviewer, a model that may approve a subagent's, team member's, or parallel branch's permission request that no human can answer: "on" (enabled), "off" (not enabled), or "inert" (configured, but an interactive approver answers instead). Clients treat other values as unknown. CHROME ONLY. Additive: an older server leaves it unset and the client shows nothing. | diff --git a/user-docs/reference/server-cli.md b/user-docs/reference/server-cli.md index d5c74c028b..438154eb90 100644 --- a/user-docs/reference/server-cli.md +++ b/user-docs/reference/server-cli.md @@ -366,13 +366,15 @@ Flags: precedence; configured deny and ask rules always override allows. --permission-mode string permission mode, one of: plan, default, accept-edits, auto, yolo. Sets two - things: the process-wide posture, fixed at startup (strict for plan, default, - and accept-edits; auto; yolo), and the session mode new sessions start in, - which each session may change. Default: default. auto and yolo allow tools - without asking, so they need a guardrails checker (--guardrails-model) or an - explicit --guardrails off, and are refused for root unless MECATL_SANDBOX=1 or - IS_SANDBOX=1. Deny rules and configured ask rules still apply. Replaces the - deprecated --posture and --yolo; --trust-project still combines with it. + things: the mode new sessions start in, and the process-wide server ceiling, + fixed at startup, which is the most permissive mode a session may switch to + (accept-edits for plan, default, and accept-edits). Default: default. auto and + yolo allow tools without asking. auto needs an enforcing guardrails checker (-- + guardrails-model or the guardrail model slot) and refuses to start without one; + yolo runs without one. Both are refused for root unless MECATL_SANDBOX=1 or + IS_SANDBOX=1. Deny rules and configured ask rules still apply. A mode never + grants project trust; use --trust-project. Replaces the deprecated --posture + and --yolo. --permissions-conventional load project and user permission settings for each session. Enabled by default. Project allow rules require --trust-project; project deny and ask rules always @@ -819,14 +821,15 @@ Usage: mecak8s [flags] Trusted permission YAML file. Repeatable --permission-mode string Permission mode, one of: plan, default, accept-edits, auto, yolo. Sets two - things: the process-wide posture, fixed at startup (strict for plan, default, - and accept-edits; auto; yolo), and the session mode new sessions start in, - which each session may change. Default: auto (posture auto, auto session mode). - auto and yolo allow tools without asking, so they need a guardrails checker (-- - guardrails-model or the guardrail model slot) or an explicit --guardrails off, - and require MECATL_SANDBOX when running as root. Deny rules and configured ask - rules still apply. Replaces the deprecated --posture; --trust-project still - combines with it + things: the mode new sessions start in, and the process-wide server ceiling, + fixed at startup, which is the most permissive mode a session may switch to + (accept-edits for plan, default, and accept-edits). Default: auto. auto and + yolo allow tools without asking and require MECATL_SANDBOX when running as + root. auto needs an enforcing guardrails checker (--guardrails-model or the + guardrail model slot) and refuses to start without one, including with -- + guardrails off; yolo runs without one. Deny rules and configured ask rules + still apply. A mode never grants project trust; use --trust-project. Replaces + the deprecated --posture --permissions-conventional Discover project and user permission settings for each session (default true) --posture string diff --git a/user-docs/reference/typescript-sdk-api/core.md b/user-docs/reference/typescript-sdk-api/core.md index 4ba1c82cda..d3ed6ab7e7 100644 --- a/user-docs/reference/typescript-sdk-api/core.md +++ b/user-docs/reference/typescript-sdk-api/core.md @@ -4513,6 +4513,14 @@ readonly storageCleanup: boolean; readonly storageHealth: boolean; ``` +ServerCapabilities.subagentAskReviewer + +Subagent ask reviewer state: `"on"`, `"off"`, or `"inert"`; treat other values as unknown. Absent from older servers. + +```ts +readonly subagentAskReviewer?: string; +``` + ServerCapabilities.teams ```ts @@ -7494,6 +7502,7 @@ ServerFeature: { readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; + readonly SessionPermissionModes: "session_permission_modes"; readonly SkillFiles: "skill_files"; readonly WatchSessionEvents: "watch_session_events"; } @@ -7530,6 +7539,8 @@ SessionMode: { readonly Default: 1; readonly Plan: 2; readonly AcceptEdits: 3; + readonly Auto: 4; + readonly Yolo: 5; } ``` From d714ac066fcffa2fe80524baaf4909dbad342483 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 13:33:17 +0300 Subject: [PATCH 25/48] fix(ci): run kind fixtures in yolo and drop stale --guardrails base arg Three CI jobs failed on the rebased head; each followed from this branch's own contract changes: - deploy:check required --guardrails among the chart's base args, but the chart now emits a guardrails flag only for an explicit checker choice (empty means inherit). Drop it from the base-arg list. - The kind fixtures (values-kind.yaml and the execution qualification values) install the chart's default permissionMode auto with the mock provider and no checker, and auto now refuses to start without an enforcing checker, so the pod never became ready and helm --wait timed out. Set permissionMode: yolo, which is what the old chart's --posture=auto --guardrails=off amounted to. - The microVM daily journey created its session with an explicit ModeDefault, which no longer inherits the process allow-all, so its Write waited on an approval nobody gives until the 1200s timeout. Use the unspecified mode so the deployment default applies, as the test's "ordinary no-selector API" comment intends. Co-authored-by: Mecatl --- Taskfile.yml | 2 +- deploy/helm/mecak8s/values-kind.yaml | 3 +++ deploy/mecatl-execution-kind/mecak8s-values.yaml | 3 +++ internal/adapter/microvm/production_e2e_test.go | 5 +++-- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index d1c032ba32..6a062d239b 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -864,7 +864,7 @@ tasks: set -eu -o pipefail missing="" rendered=$(helm template production deploy/helm/mecak8s --set '{{.SAFE_SET}}') - for arg in --grpc-addr --http-addr --redis-url --session-lease-k8s-namespace --headless --permission-mode --guardrails --oidc-issuer --oidc-audience --oidc-max-jwks-staleness=1h; do + for arg in --grpc-addr --http-addr --redis-url --session-lease-k8s-namespace --headless --permission-mode --oidc-issuer --oidc-audience --oidc-max-jwks-staleness=1h; do echo "$rendered" | grep -q -- "$arg" || missing="$missing $arg" done if [ -n "$missing" ]; then diff --git a/deploy/helm/mecak8s/values-kind.yaml b/deploy/helm/mecak8s/values-kind.yaml index 9e059a904d..d77d4acf62 100644 --- a/deploy/helm/mecak8s/values-kind.yaml +++ b/deploy/helm/mecak8s/values-kind.yaml @@ -15,6 +15,9 @@ image: pullPolicy: IfNotPresent mockProvider: true +# The mock provider has no guardrails checker, and auto refuses to start +# without one; yolo keeps the fixture's unchecked autonomous behavior. +permissionMode: yolo redis: endpoint: redis:6379 diff --git a/deploy/mecatl-execution-kind/mecak8s-values.yaml b/deploy/mecatl-execution-kind/mecak8s-values.yaml index 6eadc297d0..14c368e242 100644 --- a/deploy/mecatl-execution-kind/mecak8s-values.yaml +++ b/deploy/mecatl-execution-kind/mecak8s-values.yaml @@ -1,6 +1,9 @@ fullnameOverride: mecak8s replicaCount: 1 mockProvider: true +# The mock provider has no guardrails checker, and auto refuses to start +# without one; yolo keeps the fixture's unchecked autonomous behavior. +permissionMode: yolo redis: endpoint: redis:6379 credentialsSecret: "" diff --git a/internal/adapter/microvm/production_e2e_test.go b/internal/adapter/microvm/production_e2e_test.go index 78fac1a2e8..bf66347979 100644 --- a/internal/adapter/microvm/production_e2e_test.go +++ b/internal/adapter/microvm/production_e2e_test.go @@ -203,8 +203,9 @@ func TestMicroVMDefaultPlacementDailyHarnessJourney(t *testing.T) { t.Cleanup(built.Close) // This is deliberately the ordinary no-selector API. The deployment, not the - // client, chooses microvm-local as the default placement. - sess, err := built.Service.CreateSession(ctx, session.ModeDefault, session.Limits{}) + // client, chooses microvm-local as the default placement, and the unspecified + // mode resolves to the deployment's allow-all default. + sess, err := built.Service.CreateSession(ctx, "", session.Limits{}) if err != nil { t.Fatalf("normal CreateSession: %v", err) } From 7ba5899c40f3c5ddd9258ce6f73eb3c327707fde Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 15:28:18 +0300 Subject: [PATCH 26/48] test(e2e): create kind e2e sessions in the deployment default mode The kind e2e and execution qualification suites created every session with an explicit "mode":"default". Under the old chart's --posture=auto that still carried process-wide allow-all; with session-scoped modes an explicit default means ordinary approvals, so the learned-skill run and the borrowed-schedule proof write waited on asks nobody answers until their deadlines. Omit the mode for sessions that go on to run tools so they start in the deployment default (yolo in the Kind fixtures). Rejection-only creates keep their explicit mode. Co-authored-by: Mecatl --- e2e/k8s/caller_identity_test.go | 5 +++-- e2e/k8s_execution/live_qualification_test.go | 2 +- e2e/k8s_execution/production_qualification_test.go | 2 +- e2e/k8s_execution/qualification_test.go | 5 +++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/e2e/k8s/caller_identity_test.go b/e2e/k8s/caller_identity_test.go index 899f466c7f..0c520c32fd 100644 --- a/e2e/k8s/caller_identity_test.go +++ b/e2e/k8s/caller_identity_test.go @@ -40,9 +40,10 @@ import ( // the unauthenticated base. Caller identity is inherently MULTI-caller, so these // take the bearer per call rather than reading one shared credential. +// defaultSessionCreateBody omits the mode so the session starts in the +// deployment's default permission mode (the Kind values select yolo). func defaultSessionCreateBody() []byte { - body, _ := json.Marshal(map[string]any{"mode": "default"}) - return body + return []byte(`{}`) } func createSessionAs(ctx context.Context, addr, bearer string) (int, string) { diff --git a/e2e/k8s_execution/live_qualification_test.go b/e2e/k8s_execution/live_qualification_test.go index c1681bee16..4b44c3506d 100644 --- a/e2e/k8s_execution/live_qualification_test.go +++ b/e2e/k8s_execution/live_qualification_test.go @@ -854,7 +854,7 @@ func createLiveSession(t *testing.T, ctx context.Context, addr, token string) li t.Fatal("exact live execution template revision unavailable") } bodyJSON, err := json.Marshal(map[string]any{ - "mode": "default", "limits": map[string]int{"max_turns": 8, "max_tool_calls": 20, "max_consecutive_failures": 3}, + "limits": map[string]int{"max_turns": 8, "max_tool_calls": 20, "max_consecutive_failures": 3}, "execution": map[string]any{"template": map[string]string{"id": "go", "revision": revision}}, }) if err != nil { diff --git a/e2e/k8s_execution/production_qualification_test.go b/e2e/k8s_execution/production_qualification_test.go index e7a0a9d6f2..af32ee610b 100644 --- a/e2e/k8s_execution/production_qualification_test.go +++ b/e2e/k8s_execution/production_qualification_test.go @@ -1329,7 +1329,7 @@ func TestKindExecutionProductionPendingDeleteOutageRecovery(t *testing.T) { func createSessionAfterProviderReload(t *testing.T, ctx context.Context, addr, token string) string { t.Helper() - body := []byte(`{"mode":"default","limits":{"max_turns":16,"max_tool_calls":24,"max_consecutive_failures":3}}`) + body := []byte(`{"limits":{"max_turns":16,"max_tool_calls":24,"max_consecutive_failures":3}}`) deadline := time.Now().Add(90 * time.Second) for { status, response := request(t, ctx, http.MethodPost, "http://"+addr+"/v1/sessions", token, body) diff --git a/e2e/k8s_execution/qualification_test.go b/e2e/k8s_execution/qualification_test.go index 35ca3d09f6..129f558d0d 100644 --- a/e2e/k8s_execution/qualification_test.go +++ b/e2e/k8s_execution/qualification_test.go @@ -844,7 +844,7 @@ func fixtureToken(t *testing.T, ctx context.Context, addr, pki, sub string) stri } func createSessionTemplate(t *testing.T, ctx context.Context, addr, token, id, revision string) string { t.Helper() - body, err := json.Marshal(map[string]any{"mode": "default", "execution": map[string]any{"template": map[string]string{"id": id, "revision": revision}}}) + body, err := json.Marshal(map[string]any{"execution": map[string]any{"template": map[string]string{"id": id, "revision": revision}}}) if err != nil { t.Fatal(err) } @@ -863,7 +863,8 @@ func createSessionTemplate(t *testing.T, ctx context.Context, addr, token, id, r func createSession(t *testing.T, ctx context.Context, addr, token string, templateRevision ...string) string { t.Helper() - body := map[string]any{"mode": "default", "limits": map[string]int{"max_turns": 16, "max_tool_calls": 24, "max_consecutive_failures": 3}} + // No mode: sessions start in the deployment default (the fixture selects yolo). + body := map[string]any{"limits": map[string]int{"max_turns": 16, "max_tool_calls": 24, "max_consecutive_failures": 3}} if len(templateRevision) > 0 { body["execution"] = map[string]any{"template": map[string]string{"id": "go", "revision": templateRevision[0]}} } From d2e5fe25a88180c9ce8f82e1728d899f4654085e Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 15:28:43 +0300 Subject: [PATCH 27/48] style(e2e): gofmt the live qualification create body Co-authored-by: Mecatl --- e2e/k8s_execution/live_qualification_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/k8s_execution/live_qualification_test.go b/e2e/k8s_execution/live_qualification_test.go index 4b44c3506d..5b4b2213e2 100644 --- a/e2e/k8s_execution/live_qualification_test.go +++ b/e2e/k8s_execution/live_qualification_test.go @@ -854,7 +854,7 @@ func createLiveSession(t *testing.T, ctx context.Context, addr, token string) li t.Fatal("exact live execution template revision unavailable") } bodyJSON, err := json.Marshal(map[string]any{ - "limits": map[string]int{"max_turns": 8, "max_tool_calls": 20, "max_consecutive_failures": 3}, + "limits": map[string]int{"max_turns": 8, "max_tool_calls": 20, "max_consecutive_failures": 3}, "execution": map[string]any{"template": map[string]string{"id": "go", "revision": revision}}, }) if err != nil { From 2e192837d00367498414d9d0c473edb228ce4a6c Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:21:53 +0300 Subject: [PATCH 28/48] fix(permissions): admit auto only when an enforcing guardrail rule compiles The auto admission gate and the checker startup state read the raw guardrail specs, while the installed reviewer runs on the rules that survive CompileRule. Settings decoding accepts phases and matchers that CompileRule rejects, so an operator rule marked block with an invalid phase passed admission, was then skipped at compile time, and left auto with no contextual reviewer at all. A whitespace-padded advisory mode was also misread as block before compilation normalized it. Admission and the checker state now compile the effective rules the same way buildGuardrailsActionReviewer does, refuse auto unless an enforcing rule survives, and report the checker disabled when nothing compiles. Deterministic Deny and Ask rules are unaffected. Co-Authored-By: Claude Opus 5.5 --- internal/app/permission_mode.go | 47 +++++++++++++++++++++------ internal/app/permission_mode_test.go | 48 ++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 04cfd5aaf9..1186b3dfa0 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -7,7 +7,6 @@ import ( "github.com/stacklok/mecatl/engine/port" "github.com/stacklok/mecatl/engine/session" - "github.com/stacklok/mecatl/internal/adapter/modelhook" "github.com/stacklok/mecatl/internal/adapter/permconfig" ) @@ -241,27 +240,57 @@ func checkerState(cfg Config, configured bool) (state, reason string) { return checkerDisabled, "kill-switch (--guardrails off)" case !configured: return checkerDisabled, "no checker configured" + } + compiled, enforcing := compiledGuardrailEnforcement(cfg) + switch { + case !compiled: + return checkerDisabled, noGuardrailRuleCompiled case cfg.MaxAllowedMode == session.ModeYolo: return checkerAdvisory, "demoted in yolo-mode sessions; other modes keep it enforcing" - } - specs, _ := effectiveGuardrailSpecs(cfg) - if highestSeverityGuardrailMode(specs) == string(modelhook.ModeAdvisory) { + case !enforcing: return checkerAdvisory, "configured advisory" } return checkerEnforcing, "" } +// noGuardrailRuleCompiled is the disabled reason when every configured rule +// fails compilation, so no reviewer is installed at runtime. +const noGuardrailRuleCompiled = "no guardrail rule compiled; every configured rule has an invalid match, mode, or phases" + +// compiledGuardrailEnforcement compiles the effective rules exactly as the +// installed reviewer does (buildGuardrailsActionReviewer) and reports whether +// any rule survived and whether a surviving rule enforces. Raw specs are not +// enough: settings decoding accepts matchers and phases CompileRule rejects, +// no reviewer is installed when nothing compiles, and CompileRule normalizes +// the mode spelling. The per-rule WARNs stay with the engine build. +func compiledGuardrailEnforcement(cfg Config) (compiled, enforcing bool) { + cfg.Diagnostics = port.NopDiagnostics{} + specs, _ := effectiveGuardrailSpecs(cfg) + rules, ok := compileGuardrailRules(cfg, specs) + if !ok { + return false, false + } + for _, rule := range rules { + if !rule.Advisory() { + return true, true + } + } + return true, false +} + // autoCheckerEnforcing reports whether an auto session runs with an enforcing -// checker. Unlike checkerState it ignores the yolo demotion, which applies per -// session mode (guardrailsDemoted): an auto session on a yolo server still -// compiles its rules enforcing. +// checker: a configured checker plus at least one compiled enforcing rule, the +// same condition under which the runtime installs an enforcing reviewer. +// Unlike checkerState it ignores the yolo demotion, which applies per session +// mode (guardrailsDemoted): an auto session on a yolo server still compiles its +// rules enforcing. func autoCheckerEnforcing(cfg Config, configured bool) bool { if cfg.GuardrailsDisabled || !configured { return false } cfg.guardrailSessionMode = session.ModeAuto - specs, _ := effectiveGuardrailSpecs(cfg) - return highestSeverityGuardrailMode(specs) != string(modelhook.ModeAdvisory) + _, enforcing := compiledGuardrailEnforcement(cfg) + return enforcing } // Subagent ask reviewer states: the stable vocabulary of the diff --git a/internal/app/permission_mode_test.go b/internal/app/permission_mode_test.go index 4fc96b0582..6264b844b3 100644 --- a/internal/app/permission_mode_test.go +++ b/internal/app/permission_mode_test.go @@ -149,6 +149,54 @@ func TestAutoTokenRequiresEnforcingChecker(t *testing.T) { built.Close() } +func TestAutoAdmissionUsesCompiledGuardrailRules(t *testing.T) { + // Admission follows the rules the installed reviewer compiles, not the raw + // specs: settings decoding accepts matchers and phases CompileRule rejects, + // and it validates a padded mode trimmed while CompileRule normalizes it. + refused := map[string]string{ + "invalid phase": "guardrails:\n rules:\n - match: Shell\n phases: [during]\n mode: block\n", + "blank matcher": "guardrails:\n rules:\n - match: \" \"\n mode: block\n", + "padded advisory mode": "guardrails:\n rules:\n - match: Shell\n mode: \" advisory \"\n", + "only the advisory rule compiles": "guardrails:\n rules:\n - match: Shell\n phases: [during]\n mode: block\n" + + " - match: WebFetch\n mode: advisory\n", + } + for name, body := range refused { + cfg := permissionModeCfg(t, "auto", port.NopDiagnostics{}) + cfg.GuardrailsModel = "mock-checker" + cfg.PermissionConfigs = []string{writeOperatorSettingsFile(t, body)} + if built, err := buildIsolated(t, context.Background(), cfg); err == nil { + built.Close() + t.Errorf("%s: auto must refuse when no enforcing rule survives compilation", name) + } else if !strings.Contains(err.Error(), "requires an enforcing guardrails checker") { + t.Errorf("%s: refusal must name the requirement; got %v", name, err) + } + } + + // A yolo server with no compiled enforcing rule must not advertise auto. + yolo := permissionModeCfg(t, "yolo", port.NopDiagnostics{}) + yolo.GuardrailsModel = "mock-checker" + yolo.PermissionConfigs = []string{writeOperatorSettingsFile(t, refused["invalid phase"])} + built, err := buildIsolated(t, context.Background(), yolo) + if err != nil { + t.Fatalf("yolo with uncompilable rules must still start: %v", err) + } + if _, err := built.Service.CreateSession(context.Background(), session.ModeAuto, defaultLimits()); err == nil { + t.Error("yolo with no compiled enforcing rule must refuse an auto session") + } + built.Close() + + // A valid enforcing rule surviving next to an invalid one admits auto. + ok := permissionModeCfg(t, "auto", port.NopDiagnostics{}) + ok.GuardrailsModel = "mock-checker" + ok.PermissionConfigs = []string{writeOperatorSettingsFile(t, refused["invalid phase"]+ + " - match: NoSuchTool_inert_checker_rule\n mode: block\n")} + built, err = buildIsolated(t, context.Background(), ok) + if err != nil { + t.Fatalf("auto with a compiled enforcing rule must start: %v", err) + } + built.Close() +} + func TestYoloTokenStartsWithoutChecker(t *testing.T) { // Unchecked autonomy is yolo: it starts with no checker, WARNing only that // its sessions cannot enter auto, and refuses an auto session at runtime. From df9803f45537ba748dab45c5ab8aed59b998c5c8 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:26:10 +0300 Subject: [PATCH 29/48] fix(permissions): derive legacy mode and ceiling after the full alias fold The deprecated --posture branch of foldPermissionMode wrote the default session mode and server ceiling from the --posture value before resolvePosture applied the --yolo and --trust-project MAX fold, and the Build fallback then skipped recomputing them because they were already set. So --posture strict --yolo started yolo-posture sessions in default mode under an accept-edits ceiling, and --posture auto --yolo was refused as an auto deployment without a checker, while --yolo alone resolves to yolo with a yolo ceiling. The deprecated surface now derives both values once, from the posture after the full alias fold, so a combination lands on the same pair as the raised tier alone. Permission-mode tokens are unchanged. Co-Authored-By: Claude Opus 5.5 --- cmd/mecated/permission_mode_test.go | 38 +++++++++++++++++++++++++++++ internal/app/build.go | 12 ++++----- internal/app/permission_mode.go | 9 ++++--- internal/app/posture.go | 4 +-- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/cmd/mecated/permission_mode_test.go b/cmd/mecated/permission_mode_test.go index 02af160972..b233778d83 100644 --- a/cmd/mecated/permission_mode_test.go +++ b/cmd/mecated/permission_mode_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "log/slog" "strings" "testing" @@ -133,6 +134,43 @@ func TestAliasCombinationsStillResolve(t *testing.T) { } } +// TestCombinedLegacyAliasesBuildRaisedPair drives the real flag, appConfig, and +// app.Build path: a deprecated --posture combined with --yolo must land on the +// session mode and ceiling of the raised tier, exactly as --yolo alone does, +// not on the pair the lower --posture value implies. +func TestCombinedLegacyAliasesBuildRaisedPair(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + for _, argv := range [][]string{ + {"--yolo"}, + {"--posture", "strict", "--yolo"}, + {"--posture", "auto", "--yolo"}, + } { + t.Run(strings.Join(argv, " "), func(t *testing.T) { + cfg, err := parseFlags(append([]string{"--workspace", t.TempDir(), "--guardrails", "off"}, argv...)) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + ac := appConfig(cfg, nil, nil, nil, nil, port.NopDiagnostics{}) + ac.UseMock, ac.NoSoul, ac.Privileged = true, true, false + built, err := buildIsolated(t, context.Background(), ac) + if err != nil { + t.Fatalf("app.Build: %v", err) + } + defer built.Close() + sess, err := built.Service.CreateSession(context.Background(), "", session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + if sess.Mode != session.ModeYolo { + t.Fatalf("%q: unspecified-mode session started in %q, want yolo", argv, sess.Mode) + } + if _, err := built.Service.CreateSession(context.Background(), session.ModeYolo, session.Limits{}); err != nil { + t.Fatalf("%q: the yolo ceiling must admit a yolo session: %v", argv, err) + } + }) + } +} + func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { for _, tc := range []struct { name string diff --git a/internal/app/build.go b/internal/app/build.go index 8473e2b374..ac8ace8c86 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -1712,13 +1712,11 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { cfg = foldOperatorSteer(cfg) cfg.Posture = resolvePosture(cfg, postureNoCeiling) cfg = applyPosture(cfg) - // Backward-compat: the deprecated --yolo alias (AllowAllTools=true) only sets - // AllowAllTools, not DefaultSessionMode/MaxAllowedMode, which foldPermissionMode - // only sets when --permission-mode or --posture is explicitly given. Catch the - // remaining case here: if DefaultSessionMode is still unset after the full fold, - // derive it from the resolved posture so --yolo and Config{AllowAllTools:true} - // behave correctly (sessions start in ModeYolo, not ModeDefault). - if cfg.DefaultSessionMode == "" { + // Deprecated surface (--posture, --yolo, --trust-project, the posture: key): + // derive the session mode and ceiling from the posture AFTER the full alias + // fold, so a combination such as --posture strict --yolo lands on the same + // pair as the raised tier alone. A permission-mode token already set both. + if cfg.permissionModeName == "" { cfg.DefaultSessionMode, cfg.MaxAllowedMode = postureToSessionModes(cfg.Posture) } // AUTHORITATIVE root/no-sandbox refusal: applied HERE, after the full posture fold, diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 1186b3dfa0..7d6e18be62 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -106,10 +106,11 @@ func foldPermissionMode(cfg Config) (Config, error) { case cfg.PermissionModeFlagSet: raw, source = cfg.PermissionMode, "--permission-mode" case cfg.PostureFlagSet: - // Deprecated --posture: set DefaultSessionMode and MaxAllowedMode from the - // resolved posture for backward compat. The posture is already on cfg.Posture - // (set by the cmd layer); foldOperatorPosture would no-op since PostureFlagSet. - cfg.DefaultSessionMode, cfg.MaxAllowedMode = postureToSessionModes(cfg.Posture) + // Deprecated --posture: the posture is already on cfg.Posture (set by the + // cmd layer); foldOperatorPosture would no-op since PostureFlagSet. The + // session mode and ceiling are NOT derived here: --yolo and --trust-project + // may still raise the posture, so Build derives them after the full alias + // fold. return foldOperatorPosture(cfg), nil default: if res, ok := cfg.permResolver.(*permconfig.Resolver); ok && res != nil { diff --git a/internal/app/posture.go b/internal/app/posture.go index bc0468b00c..1ea31bbe46 100644 --- a/internal/app/posture.go +++ b/internal/app/posture.go @@ -214,8 +214,8 @@ func resolvePosture(cfg Config, ceiling Posture) Posture { // Allow-all and loose-substitution are no longer derived here: they are // mode-driven (Policy.Evaluate injects allowAllCLIRules for ModeAuto/ModeYolo // at call time). DefaultSessionMode and MaxAllowedMode are set by foldPermissionMode -// (for explicit token/posture flags) or by the backward-compat fallback in Build() -// (for the deprecated --yolo alias path). +// (for a permission-mode token) or, after the full alias fold, by Build() +// (for the deprecated --posture/--yolo/--trust-project surface). // // A posture written by a --permission-mode token or the permissionMode: key // derives NO trust: workspace trust is a separate decision taken only from From c257622626c6e6141788fa09670889bca752a148 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:23:48 +0300 Subject: [PATCH 30/48] fix(permissions): re-admit the stored mode under the acquired lease Run entry admitted the pre-lease snapshot only. During a rolling upgrade a looser peer could take the session lease and save a mode this replica refuses while it waited, and the reload under the lease then executed that mode unchecked. Every run entry now re-admits the authoritative snapshot once the lease is held, before recovery effects or engine construction; each reload that replaces the run's aggregate re-admits it; and both launch fences check the mode of the aggregate about to execute, not just lease ownership. Construction now runs the complete admission on the default mode and validates the ceiling, so a service whose default sessions could never be created fails to start instead of failing every default CreateSession. Co-Authored-By: Claude Opus 5.5 --- internal/adapter/server/exact_plan_ask.go | 3 + .../adapter/server/mode_admission_test.go | 149 ++++++++++++++++++ internal/adapter/server/service.go | 80 ++++++++-- 3 files changed, 218 insertions(+), 14 deletions(-) diff --git a/internal/adapter/server/exact_plan_ask.go b/internal/adapter/server/exact_plan_ask.go index c2974db7fe..9dedb34b2f 100644 --- a/internal/adapter/server/exact_plan_ask.go +++ b/internal/adapter/server/exact_plan_ask.go @@ -173,6 +173,9 @@ func (s *Service) resolvePersistedPlanAsk(ctx context.Context, id session.Sessio if err := s.validatePersistedPlanAsk(sess, expectedRunID, askID); err != nil { return RunAskAcknowledgement{}, err } + if err := s.admitStoredMode(sess); err != nil { + return RunAskAcknowledgement{}, err + } st.persistMu.Lock() s.mu.Lock() if s.runs[id] != st || st.cancelling || st.cancelSignaled { diff --git a/internal/adapter/server/mode_admission_test.go b/internal/adapter/server/mode_admission_test.go index 61d18c225f..141f4651c3 100644 --- a/internal/adapter/server/mode_admission_test.go +++ b/internal/adapter/server/mode_admission_test.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httptest" "strings" + "sync" "testing" "time" @@ -14,9 +15,11 @@ import ( "google.golang.org/grpc/status" mecatlv1 "github.com/stacklok/mecatl/contracts/gen/go/mecatl/v1" + "github.com/stacklok/mecatl/engine/adapter/memlease" "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/adapter/wallclock" "github.com/stacklok/mecatl/engine/agent" "github.com/stacklok/mecatl/engine/port" "github.com/stacklok/mecatl/engine/session" @@ -174,6 +177,42 @@ func TestAutoDefaultWithoutCheckerRefusedAtConstruction(t *testing.T) { } } +// TestInadmissibleDefaultModeRefusedAtConstruction pins that construction +// runs the complete session admission on the default mode and validates the +// ceiling, so a service that could never create its default session fails to +// start instead of failing every default CreateSession. +func TestInadmissibleDefaultModeRefusedAtConstruction(t *testing.T) { + for _, tc := range []struct { + name string + def, ceiling session.PermissionMode + checker bool + wantErrSubstring string + }{ + {"unknown default", "bogus", session.ModeYolo, true, "unknown permission mode"}, + {"default above ceiling", session.ModeYolo, session.ModeAccept, true, "exceeds the server ceiling"}, + {"auto default above ceiling", session.ModeAuto, session.ModeDefault, true, "exceeds the server ceiling"}, + {"unknown ceiling", session.ModeDefault, "bogus", true, "unknown permission-mode ceiling"}, + } { + t.Run(tc.name, func(t *testing.T) { + _, err := newPlacementTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(nil, nil), Model: "test-model"}), + Store: memstore.New(), + PlacementProvider: testPlacementProvider{}, + PlacementScope: "test", + DefaultMode: tc.def, + MaxAllowedMode: tc.ceiling, + EnforcingCheckerConfigured: tc.checker, + }) + if !errors.Is(err, server.ErrConfig) || !strings.Contains(err.Error(), tc.wantErrSubstring) { + t.Fatalf("err = %v, want ErrConfig containing %q", err, tc.wantErrSubstring) + } + }) + } + // Positive control: a default at the ceiling, and any default with no ceiling. + modeAdmissionService(t, session.ModeAccept, session.ModeAccept, false) + modeAdmissionService(t, "", session.ModeYolo, false) +} + // TestAutoRequiresCheckerEvenWhenNotDefault pins that, without an enforcing // checker, explicit auto creation and switching (back) to auto are refused on // every ceiling that would otherwise admit auto, while yolo stays admissible. @@ -260,6 +299,116 @@ func TestStoredModeReadmittedAfterTighterRestart(t *testing.T) { } } +// gatedLease parks the named owner's first Acquire until release closes, so +// a test can let a peer mutate the session while that owner waits for the +// lease after its pre-lease admission. +type gatedLease struct { + port.SessionLease + owner string + entered chan struct{} + release chan struct{} + once sync.Once +} + +func (l *gatedLease) Acquire(ctx context.Context, id session.SessionID, owner string) (port.Lease, error) { + if owner == l.owner { + first := false + l.once.Do(func() { first = true }) + if first { + close(l.entered) + <-l.release + } + } + return l.SessionLease.Acquire(ctx, id, owner) +} + +// leasedModeService is modeAdmissionServiceOn sharing a lease backend, so two +// services model replicas on different configurations during a rollout. +func leasedModeService(t *testing.T, store port.SessionStore, lease port.SessionLease, owner string, llm *mockllm.Provider, ceiling session.PermissionMode) *server.Service { + t.Helper() + svc, err := newPlacementTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{ + LLM: llm, + Catalog: tool.NewCatalog(), + Policy: permpolicy.NewPolicy(allowRules(), nil), + Model: "test-model", + }), + Store: store, + SessionLease: lease, + LeaseOwner: owner, + LeaseTTL: time.Minute, + LeaseRenewInterval: time.Hour, + DefaultCapabilities: llm.Capabilities(), + MaxAllowedMode: ceiling, + EnforcingCheckerConfigured: true, + }) + if err != nil { + t.Fatalf("new service %s: %v", owner, err) + } + t.Cleanup(svc.Close) + return svc +} + +// TestStoredModeReadmittedUnderAcquiredLease races two replicas sharing one +// store and lease backend: the stricter replica admits the pre-lease Default +// snapshot, a looser peer takes the lease and saves Yolo while it waits, and +// the stricter replica must refuse the authoritative Yolo snapshot once it +// holds the lease, before any provider work and without mutating it. +func TestStoredModeReadmittedUnderAcquiredLease(t *testing.T) { + ctx := context.Background() + store := memstore.New() + lease := &gatedLease{ + SessionLease: memlease.New(wallclock.Clock{}, time.Minute), + owner: "strict", entered: make(chan struct{}), release: make(chan struct{}), + } + looseLLM := mockllm.New() + loose := leasedModeService(t, store, lease, "loose", looseLLM, session.ModeYolo) + strictLLM := mockllm.New(mockllm.TextTurn("ran")) + strict := leasedModeService(t, store, lease, "strict", strictLLM, session.ModeAccept) + + sess, err := loose.CreateSession(ctx, session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + result := make(chan error, 1) + go func() { + run, err := strict.StartRun(ctx, sess.ID, "go") + if run != nil { + for range run.Events() { + } + strict.FinishRun(sess.ID, run) + } + result <- err + }() + select { + case <-lease.entered: + case <-time.After(5 * time.Second): + t.Fatal("strict replica never reached lease acquisition") + } + if _, err := loose.SetMode(ctx, sess.ID, session.ModeYolo); err != nil { + t.Fatalf("peer SetMode(yolo): %v", err) + } + close(lease.release) + select { + case err := <-result: + if !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("StartRun err = %v, want ErrFailedPrecondition", err) + } + case <-time.After(5 * time.Second): + t.Fatal("strict StartRun did not return") + } + if strictLLM.Calls() != 0 || looseLLM.Calls() != 0 { + t.Fatalf("provider calls strict=%d loose=%d before refusal, want 0", strictLLM.Calls(), looseLLM.Calls()) + } + kept, err := store.Load(ctx, sess.ID) + if err != nil { + t.Fatalf("Load: %v", err) + } + if kept.Mode != session.ModeYolo || kept.State != session.StateIdle { + t.Fatalf("refusal mutated the session: mode %q state %q", kept.Mode, kept.State) + } +} + // TestHTTPAutoYoloModes pins the HTTP mode mapping and the shared admission. func TestHTTPAutoYoloModes(t *testing.T) { decode := func(resp *http.Response) (int, string) { diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index fc45aad600..d228ef263c 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -4833,27 +4833,35 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio // admitStoredMode applies the same check to a persisted session at every run // entry, so a mode admitted under an earlier, looser deployment cannot execute. func (s *Service) admitMode(mode session.PermissionMode) error { + return admitModeFor(&s.cfg, mode) +} + +func admitModeFor(cfg *Config, mode session.PermissionMode) error { if modeRank(mode) == 0 { return fmt.Errorf("%w: unknown permission mode %q", ErrInvalidArgument, mode) } - if s.cfg.MaxAllowedMode != "" && !modeWithinCeiling(mode, s.cfg.MaxAllowedMode) { - return fmt.Errorf("%w: mode %q exceeds the server ceiling %q; the server must be relaunched with a higher --permission-mode to allow it", ErrInvalidArgument, mode, s.cfg.MaxAllowedMode) + if cfg.MaxAllowedMode != "" && !modeWithinCeiling(mode, cfg.MaxAllowedMode) { + return fmt.Errorf("%w: mode %q exceeds the server ceiling %q; the server must be relaunched with a higher --permission-mode to allow it", ErrInvalidArgument, mode, cfg.MaxAllowedMode) } - if mode == session.ModeAuto && !s.hasEnforcingChecker() { + if mode == session.ModeAuto && !cfg.EnforcingCheckerConfigured { return fmt.Errorf("%w: mode %q requires an enforcing guardrails checker; configure one with --guardrails-model or bind the guardrail model slot, or use yolo for gate-free autonomous operation", ErrInvalidArgument, mode) } return nil } -// normalizeDefaultMode defaults an empty DefaultMode to default and refuses -// an auto default without an enforcing checker: auto has no default-mode -// exemption. +// normalizeDefaultMode defaults an empty DefaultMode to default and runs the +// complete session admission against it, so a service whose default sessions +// could never be created (unknown mode, above the ceiling, or auto without an +// enforcing checker) fails construction instead of every default CreateSession. func normalizeDefaultMode(cfg *Config) error { + if cfg.MaxAllowedMode != "" && modeRank(cfg.MaxAllowedMode) == 0 { + return fmt.Errorf("%w: unknown permission-mode ceiling %q", ErrConfig, cfg.MaxAllowedMode) + } if cfg.DefaultMode == "" { cfg.DefaultMode = session.ModeDefault } - if cfg.DefaultMode == session.ModeAuto && !cfg.EnforcingCheckerConfigured { - return fmt.Errorf("%w: default mode %q requires an enforcing guardrails checker; configure one or use yolo for unchecked autonomous operation", ErrConfig, cfg.DefaultMode) + if err := admitModeFor(cfg, cfg.DefaultMode); err != nil { + return fmt.Errorf("%w: default mode: %v", ErrConfig, err) } return nil } @@ -4882,6 +4890,27 @@ func (s *Service) admitStoredMode(sess *session.Session) error { return nil } +// admitLeasedMode re-admits the AUTHORITATIVE stored mode once this process +// holds id's session lease. beginRunAdmission checked the pre-lease snapshot +// only: while this request waited for the lease, a peer on a looser +// configuration (a rolling upgrade) may have taken the lease and saved a mode +// this server does not admit. The caller holds runEntryMu and the lease, so +// the snapshot read here is the one any later reload observes; every later +// replacement of the run's aggregate re-admits it, and the launch fences +// check the executed aggregate once more. +func (s *Service) admitLeasedMode(ctx context.Context, id session.SessionID) error { + if s.cfg.SessionLease == nil { + // Without a shared lease there is no peer writer to race; the + // pre-lease snapshot was read under runEntryMu. + return nil + } + sess, err := s.cfg.Store.Load(ctx, id) + if err != nil { + return fmt.Errorf("%w: %q", ErrNotFound, id) + } + return s.admitStoredMode(sess) +} + // modeWithinCeiling reports whether mode is at or below ceiling in the // permission-mode ordering: plan < default < accept-edits < auto < yolo. func modeWithinCeiling(mode, ceiling session.PermissionMode) bool { @@ -4907,12 +4936,6 @@ func modeRank(mode session.PermissionMode) int { } } -// hasEnforcingChecker reports whether the service has a guardrails checker -// configured in enforcing mode. It is used to gate ModeAuto entry at SetMode time. -func (s *Service) hasEnforcingChecker() bool { - return s.cfg.EnforcingCheckerConfigured -} - // LoadSession resumes a previously-persisted session so a subsequent StartRun // continues it. It loads the latest snapshot from the store and, if the session // is in a terminal state, REOPENS/INTERRUPTS/RECOVERS it to StateIdle @@ -5527,6 +5550,9 @@ func (s *Service) RetryFailedRun(ctx context.Context, id session.SessionID) (*ag } }() ctx = admissionCtx + if err := s.admitLeasedMode(ctx, id); err != nil { + return nil, err + } engine, env, governanceRoot, err := s.engineAndEnvironmentFor(ctx, sess) if err != nil { return nil, err @@ -5752,6 +5778,9 @@ func (s *Service) startRunContentLocked(ctx context.Context, id session.SessionI } }() ctx = admissionCtx + if err := s.admitLeasedMode(ctx, id); err != nil { + return nil, err + } // Apply the unchanged reopen/interrupt/recover funnel only after the trusted // purpose and ownership gates and lease acquisition. Rejected kinds are never // mutated as a side effect of probing. @@ -5782,6 +5811,13 @@ func (s *Service) startRunContentLocked(ctx context.Context, id session.SessionI if err != nil { return nil, err } + // The reload replaced the admitted aggregate, so admit it again. An + // interrupted authorization is refused just below regardless of mode. + if !interruptedAuthorization { + if err := s.admitStoredMode(sess); err != nil { + return nil, err + } + } // interruptRestoredAuthorizationLocked may reload/replace the aggregate // (e.g. to interrupt a restored authorizing session); st.sess was captured // by beginRunAdmission above from the PRE-repair load, so it must be kept @@ -6098,6 +6134,9 @@ func (s *Service) resolvePersistedRunAsk(ctx context.Context, id session.Session if err := s.validatePersistedRunAsk(sess, expectedRunID, resolution, scoped); err != nil { return RunAskAcknowledgement{}, err } + if err := s.admitStoredMode(sess); err != nil { + return RunAskAcknowledgement{}, err + } st.persistMu.Lock() s.mu.Lock() if s.runs[id] != st || st.cancelling || st.cancelSignaled { @@ -6234,6 +6273,11 @@ func (s *Service) promoteDetachedRunAdmission(request context.Context, id sessio if err := s.validateHeldLeaseLocked(id); err != nil { return nil, err } + // The launch fence also covers the admitted mode: the aggregate about to + // execute is st.sess, whatever reload last replaced it. + if err := s.admitStoredMode(st.sess); err != nil { + return nil, err + } run := launch() st.run = run st.runContextStop = stop @@ -7655,6 +7699,9 @@ func (s *Service) resumeFromAwaiting(ctx context.Context, id session.SessionID, } }() ctx = admissionCtx + if err := s.admitLeasedMode(ctx, id); err != nil { + return nil, err + } if err := s.attachLiveInstructions(sess, true); err != nil { return nil, err } @@ -9467,6 +9514,11 @@ func (s *Service) promoteRunAdmission(id session.SessionID, st *runState, stop c if err := s.validateHeldLeaseLocked(id); err != nil { return nil, err } + // The launch fence also covers the admitted mode: the aggregate about to + // execute is st.sess, whatever reload last replaced it. + if err := s.admitStoredMode(st.sess); err != nil { + return nil, err + } run := launch() st.run = run st.runContextStop = stop From aadea21017b291f20c2e76ad9aaf4dee608cbad0 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:28:38 +0300 Subject: [PATCH 31/48] docs(permissions): describe rollback for sessions stored in auto or yolo The upgrade notes only said stored sessions keep their mode. Operators rolling back also need to know what an older server does with a snapshot whose mode it has no name for: it loads it without validation, evaluates permissions as default (plus its own process-wide posture), reports DEFAULT over gRPC, and re-saves the string unchanged so a later upgrade re-admits it. Co-Authored-By: Claude Opus 5.5 --- .../security-and-execution/permissions-and-posture.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index b20970bf53..51439a8e2b 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -263,7 +263,11 @@ and deployments can observe: Pass `--trust-project` or add the workspace to `trustedWorkspaces`. - **Stored sessions** keep their recorded mode. A session recorded in a mode the upgraded server does not admit refuses to run until its owner switches it to - an admitted mode. + an admitted mode. If you roll back to a release without session-scoped + modes, that release still loads `auto` and `yolo` sessions but treats them + as `default`: they get ordinary approvals unless that server's own + `--posture` allows all tools, and gRPC reports them as `DEFAULT`. It keeps + the stored mode, so upgrading again restores it and admits it again. Clients detect a server with session-scoped modes through the `session_permission_modes` feature identifier. The API major version is From a248d90018f3d763c4e85e523f634c7294f3918f Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:24:55 +0300 Subject: [PATCH 32/48] fix(mecatui): gate session-scoped mode semantics on session_permission_modes The mode cycle inferred the new session-scoped semantics from the legacy posture capability, and startup only checks API major 1. Against an older yolo server, cycling to default succeeded without removing that server's process-wide allow-all, yet the header presented default as the effective mode. The client now reads the session_permission_modes feature into Capabilities. Without it the ui falls back to an explicit legacy presentation: the cycle offers only plan, default, and accept-edits (an older server has no auto or yolo session mode), and the header and footer label the session mode with the server's auto or yolo posture, which still applies to every session there. Co-Authored-By: Claude Opus 5.5 --- cmd/mecatui/client/capabilities.go | 20 ++++++ cmd/mecatui/client/client.go | 2 +- cmd/mecatui/client/models_test.go | 26 ++++++++ cmd/mecatui/ui/mode_cycle.go | 59 ++++++++++++++--- cmd/mecatui/ui/mode_test.go | 1 + .../ui/permission_mode_vocabulary_test.go | 66 ++++++++++++++++++- cmd/mecatui/ui/statusline_test.go | 1 + .../permissions-and-posture.md | 4 +- 8 files changed, 166 insertions(+), 13 deletions(-) diff --git a/cmd/mecatui/client/capabilities.go b/cmd/mecatui/client/capabilities.go index cd8cf5e7be..f0419ed4c5 100644 --- a/cmd/mecatui/client/capabilities.go +++ b/cmd/mecatui/client/capabilities.go @@ -1,6 +1,8 @@ package client import ( + "slices" + mecatlv1 "github.com/stacklok/mecatl/contracts/gen/go/mecatl/v1" ) @@ -46,6 +48,12 @@ type Capabilities struct { // "yolo"). It bounds which modes the ui's mode cycle may switch to. NOT // session state. Empty on an older server. Posture string + // SessionPermissionModes reports the session_permission_modes feature: the + // five modes are session-scoped (auto and yolo are session modes, and a lower + // session mode drops the posture's allow-all). An older server without it + // applies its auto/yolo posture process-wide whatever the session mode, so the + // ui must not present a session mode as the effective permission mode there. + SessionPermissionModes bool // ProjectTrust is "trusted" or "untrusted" for the server's launch // workspace, CHROME ONLY: the ui's header badge. Empty on an older server. ProjectTrust string @@ -112,6 +120,18 @@ func capabilitiesWithSessionMediaFrom(caps Capabilities, sessionCaps *mecatlv1.S return caps } +// SessionPermissionModesFeature is the compatibility feature identifier for +// session-scoped permission modes. +const SessionPermissionModesFeature = "session_permission_modes" + +// compatibilityCapabilitiesFrom maps a compatibility response: the capability +// message plus the feature bits the ui consumes. +func compatibilityCapabilitiesFrom(resp *mecatlv1.GetCompatibilityInfoResponse) Capabilities { + caps := capabilitiesFrom(resp.GetCapabilities()) + caps.SessionPermissionModes = slices.Contains(resp.GetFeatures(), SessionPermissionModesFeature) + return caps +} + // capabilitiesFrom maps a proto ServerCapabilities (nil-safe) to the plain // struct. A nil message (older server) yields the all-false zero value. func capabilitiesFrom(c *mecatlv1.ServerCapabilities) Capabilities { diff --git a/cmd/mecatui/client/client.go b/cmd/mecatui/client/client.go index df8a382126..94853e979f 100644 --- a/cmd/mecatui/client/client.go +++ b/cmd/mecatui/client/client.go @@ -473,7 +473,7 @@ func (c *Client) compatibilityCapabilities(ctx context.Context) (Capabilities, e if err != nil { return Capabilities{}, fmt.Errorf("get compatibility info: %w", err) } - return capabilitiesFrom(resp.GetCapabilities()), nil + return compatibilityCapabilitiesFrom(resp), nil } // createSession is the shared CreateSession proto call and response unwrap body. diff --git a/cmd/mecatui/client/models_test.go b/cmd/mecatui/client/models_test.go index 219c1a7d78..6518b1008e 100644 --- a/cmd/mecatui/client/models_test.go +++ b/cmd/mecatui/client/models_test.go @@ -256,6 +256,32 @@ func TestCreateSessionUsesSessionMediaCapabilities(t *testing.T) { } } +// TestCreateSessionReadsSessionPermissionModesFeature pins that the +// session_permission_modes feature, not the legacy posture capability, decides +// whether the ui may present the session-scoped mode semantics. An API-major-1 +// server that advertises yolo posture without the feature is a legacy server. +func TestCreateSessionReadsSessionPermissionModesFeature(t *testing.T) { + for _, tc := range []struct { + name string + features []string + want bool + }{ + {name: "older yolo server without the feature", features: []string{"server_info"}, want: false}, + {name: "server advertising the feature", features: []string{"server_info", SessionPermissionModesFeature}, want: true}, + } { + t.Run(tc.name, func(t *testing.T) { + fake := &fakeModelsClient{caps: &mecatlv1.ServerCapabilities{Posture: "yolo"}, features: tc.features} + _, caps, _, err := newFakeClient(fake).CreateSession(context.Background(), mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT, ModelSelection{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + if caps.Posture != "yolo" || caps.SessionPermissionModes != tc.want { + t.Fatalf("capabilities posture=%q sessionPermissionModes=%v, want yolo/%v", caps.Posture, caps.SessionPermissionModes, tc.want) + } + }) + } +} + // TestReasoningEffortIsZero asserts an effort-only selection is NOT zero (the client // must still send it) while a fully-empty selection is. func TestReasoningEffortIsZero(t *testing.T) { diff --git a/cmd/mecatui/ui/mode_cycle.go b/cmd/mecatui/ui/mode_cycle.go index c20079dfb4..4f5f6b7dc5 100644 --- a/cmd/mecatui/ui/mode_cycle.go +++ b/cmd/mecatui/ui/mode_cycle.go @@ -6,17 +6,45 @@ import ( // modeCycleOrder is the ModeSwitch order over every permission mode: the // vocabulary with default and plan swapped, keeping the established -// default → plan → accept-edits start before the posture-raising modes. -func modeCycleOrder() []string { +// default → plan → accept-edits start before the posture-raising modes. A +// legacy server (see legacyPermissionModes) has no auto or yolo session mode, +// so its cycle stops at the three session modes it understands. +func modeCycleOrder(legacy bool) []string { vocab := PermissionModeVocabulary() - names := make([]string, len(vocab)) - for i, e := range vocab { - names[i] = e.Name + names := make([]string, 0, len(vocab)) + for _, e := range vocab { + if legacy && e.Posture != postureStrict { + continue + } + names = append(names, e.Name) } names[0], names[1] = names[1], names[0] return names } +// legacyPermissionModes reports a server without the session_permission_modes +// feature. Its auto or yolo posture is process-wide: it applies to every +// session whatever the session mode, and SetMode cannot remove it. The ui then +// cycles only the legacy session modes and labels the header with the server +// posture, so a session mode is never presented as the effective permission mode. +func (m Model) legacyPermissionModes() bool { + return !m.caps.SessionPermissionModes +} + +// legacyAllowAllPosture is the process-wide allow-all posture a legacy server +// applies over every session mode, or "" when there is none. +func (m Model) legacyAllowAllPosture() string { + if !m.legacyPermissionModes() { + return "" + } + switch m.caps.Posture { + case postureAuto, postureYolo: + return m.caps.Posture + default: + return "" + } +} + // modeCursor is the permission mode the cycle last landed on, valid only while // the session's desired mode is still the one it recorded. Any other mode change // (server read-back, new session) invalidates it, so the cycle re-derives its @@ -64,6 +92,9 @@ func (m Model) currentModeToken() string { // session mode itself. func (m Model) acceptedModeToken() string { session := m.desiredMode() + if m.legacyPermissionModes() { + return session + } for _, e := range PermissionModeVocabulary() { if e.Posture == m.caps.Posture && e.SessionMode == session { return e.Name @@ -72,8 +103,8 @@ func (m Model) acceptedModeToken() string { return session } -func nextModeToken(cur string) string { - order := modeCycleOrder() +func nextModeToken(cur string, legacy bool) string { + order := modeCycleOrder(legacy) for i, name := range order { if name == cur { return order[(i+1)%len(order)] @@ -94,7 +125,7 @@ func (m Model) cycleMode() (tea.Model, tea.Cmd) { if m.modeRefused != "" { cur, m.modeRefused = m.modeRefused, "" } - next := permissionModeEntry(nextModeToken(cur)) + next := permissionModeEntry(nextModeToken(cur, m.legacyPermissionModes())) if postureRank(next.Posture) > postureRank(m.caps.Posture) { m.modeCursor = modeCursor{token: next.Name, session: m.desiredMode()} m.statusMsg = m.deps.Theme.Style("warning").Render(m.modeUnavailableStatus(next)) @@ -132,6 +163,10 @@ func (m Model) headerMode() string { mode += " pending" } } + if posture := m.legacyAllowAllPosture(); posture != "" && mode != "" { + // An older server's allow-all posture overrides every session mode. + mode += " (server " + posture + ")" + } return mode } @@ -147,7 +182,13 @@ func (m Model) modeUnavailableStatus(e PermissionModeEntry) string { // server ceiling are fully effective — allow-all and loose-substitution are // session-mode-driven, not posture-driven, so switching to a lower mode // actually changes behavior and nothing "stays until restart". -func (Model) modeLabel(e PermissionModeEntry) string { +// +// On a legacy server with an allow-all posture the label says that posture +// still applies, because the session mode cannot lower it there. +func (m Model) modeLabel(e PermissionModeEntry) string { + if posture := m.legacyAllowAllPosture(); posture != "" { + return e.Name + " (the server's " + posture + " posture still applies to every session)" + } return e.Name } diff --git a/cmd/mecatui/ui/mode_test.go b/cmd/mecatui/ui/mode_test.go index a2771c99ff..b65666e3bf 100644 --- a/cmd/mecatui/ui/mode_test.go +++ b/cmd/mecatui/ui/mode_test.go @@ -161,6 +161,7 @@ func TestRefusedModeDoesNotTrapCycle(t *testing.T) { m := newTestModelFromDeps(Deps{Session: conv, Conv: conv, Theme: theme.New("aztec", theme.AztecPalette()), Mode: "accept-edits", Ctx: context.Background(), Embedded: true}) m = applyAll(m, tea.WindowSizeMsg{Width: 120, Height: 30}, client.SessionReadyMsg{SessionID: "sess-test-0001", Mode: "accept-edits"}) m.caps.Posture = postureYolo + m.caps.SessionPermissionModes = true press := func() { t.Helper() diff --git a/cmd/mecatui/ui/permission_mode_vocabulary_test.go b/cmd/mecatui/ui/permission_mode_vocabulary_test.go index 79c8fa714c..d32b780339 100644 --- a/cmd/mecatui/ui/permission_mode_vocabulary_test.go +++ b/cmd/mecatui/ui/permission_mode_vocabulary_test.go @@ -26,7 +26,7 @@ func permissionModeTestModel(t *testing.T, conv *fakeConv, posture string, embed }) return applyAll(m, tea.WindowSizeMsg{Width: 140, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-test-0001", Mode: "default", Capabilities: client.Capabilities{Posture: posture}}, + client.SessionReadyMsg{SessionID: "sess-test-0001", Mode: "default", Capabilities: client.Capabilities{Posture: posture, SessionPermissionModes: true}}, ) } @@ -353,7 +353,7 @@ func TestHeaderKeepsPostureAcrossModeCycle(t *testing.T) { }) m = applyAll(m, tea.WindowSizeMsg{Width: 140, Height: 30}, - client.SessionReadyMsg{SessionID: "sess-auto-cycle", Mode: "auto", Capabilities: client.Capabilities{Posture: postureAuto, ProjectTrust: client.ProjectTrusted}}, + client.SessionReadyMsg{SessionID: "sess-auto-cycle", Mode: "auto", Capabilities: client.Capabilities{Posture: postureAuto, ProjectTrust: client.ProjectTrusted, SessionPermissionModes: true}}, ) assertAuto := func(step, wantMode string) { @@ -466,3 +466,65 @@ func TestModeServerDefaultRequestsUnspecifiedAndReadsBack(t *testing.T) { t.Fatalf("desiredMode after ready = %q, want plan", got) } } + +// legacyYoloModel is a session on an API-major-1 server that predates the +// session_permission_modes feature but advertises a yolo posture: its allow-all +// is process-wide and no session mode removes it. +func legacyYoloModel(t *testing.T, conv *fakeConv) Model { + t.Helper() + m := newTestModelFromDeps(Deps{ + Session: conv, + Conv: conv, + Theme: theme.New("aztec", theme.AztecPalette()), + Mode: "default", + Ctx: context.Background(), + }) + return applyAll(m, + tea.WindowSizeMsg{Width: 140, Height: 30}, + client.SessionReadyMsg{SessionID: "sess-legacy-yolo", Mode: "default", Capabilities: client.Capabilities{Posture: postureYolo}}, + ) +} + +// TestLegacyYoloServerNeverPresentsSessionModeAsEffective pins the legacy +// presentation: against an older yolo server the header names the server's +// posture next to every session mode, the cycle offers only the session modes +// that server understands (never auto or yolo), and landing on one says the +// server's yolo still applies. +func TestLegacyYoloServerNeverPresentsSessionModeAsEffective(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := legacyYoloModel(t, conv) + if got := statusMode(m); got != "default (server yolo)" { + t.Fatalf("start: status mode = %q, want the server posture named", got) + } + want := []string{"plan", "accept-edits", "default", "plan"} + for i, mode := range want { + var issued bool + m, issued = pressModeSwitch(t, m) + if !issued { + t.Fatalf("step %d: no SetMode issued for %s", i, mode) + } + if got := statusMode(m); got != mode+" (server yolo)" { + t.Fatalf("step %d: status mode = %q, want %q", i, got, mode+" (server yolo)") + } + if status := visibleModeText(m); !strings.Contains(status, "yolo posture still applies") { + t.Fatalf("step %d: status = %q, want the posture caveat", i, status) + } + } + for _, sent := range conv.setModes() { + if sent == "auto" || sent == "yolo" { + t.Fatalf("SetMode calls = %v: a legacy server has no %s session mode", conv.setModes(), sent) + } + } +} + +// TestLegacyStrictServerShowsPlainSessionMode pins that the legacy label is +// only added for an allow-all posture: a strict older server's session mode is +// its effective mode. +func TestLegacyStrictServerShowsPlainSessionMode(t *testing.T) { + conv := &fakeConv{recv: &fakeRecver{}, send: &fakeSender{}, mode: "default"} + m := legacyYoloModel(t, conv) + m.caps.Posture = postureStrict + if got := statusMode(m); got != "default" { + t.Fatalf("status mode = %q, want default", got) + } +} diff --git a/cmd/mecatui/ui/statusline_test.go b/cmd/mecatui/ui/statusline_test.go index b2ece490d8..0ae96a1e3b 100644 --- a/cmd/mecatui/ui/statusline_test.go +++ b/cmd/mecatui/ui/statusline_test.go @@ -63,6 +63,7 @@ func TestStatusLine_YoloModeRendersAlarmPill(t *testing.T) { m.phase = phaseIdle m.activeMode = mode m.caps.Posture = postureYolo + m.caps.SessionPermissionModes = true updated, _ := m.Update(tea.WindowSizeMsg{Width: 100, Height: 24}) m = updated.(Model) updated, _ = m.update(waitStatusMessage(t, m.statusLineWaitCmd())) diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index 51439a8e2b..ac29b41d8e 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -271,7 +271,9 @@ and deployments can observe: Clients detect a server with session-scoped modes through the `session_permission_modes` feature identifier. The API major version is -unchanged. +unchanged. Against an older server without that feature, `mecatui` cycles only +`plan`, `default`, and `accept-edits`, and labels the header mode with the +server's `auto` or `yolo` posture, which still applies to every session there. ## Approve and constrain work From 9d03d66087182d42d1ed610ae34bcd580a8087a5 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:30:22 +0300 Subject: [PATCH 33/48] fix(studio): report auto and yolo sessions instead of showing them as Manual The BFF folded the auto and yolo session modes into default, so a chat created elsewhere in an autonomous mode read as Manual ("Always ask before making changes") and lost its header badge. Rendering does not change execution, but the description of the session was wrong. Session detail and set-mode responses now carry the reported mode, including auto and yolo. Studio still never requests those modes: the request schema keeps its three values. A chat in auto or yolo shows a warning or destructive badge, labels the mode "set outside Studio" in its details, and gets no Mode control, since Studio cannot show or restore it there. Co-Authored-By: Claude Opus 5.5 --- apps/contracts/openapi.json | 8 +++++-- apps/contracts/src/generated/types.gen.ts | 4 ++-- apps/contracts/src/schemas/chat.ts | 10 ++++++-- apps/server/src/mecatl/chat.test.ts | 24 +++++++++++++++++++ apps/server/src/mecatl/chat.ts | 8 +++++-- .../chat/chat-composer.alignment.test.tsx | 19 +++++++++++++++ apps/web/src/features/chat/chat-workspace.tsx | 11 +++++++-- .../features/chat/permission-mode-badge.tsx | 14 ++++++++--- .../features/chat/session-details-dialog.tsx | 2 ++ apps/web/src/lib/permission-mode.ts | 16 +++++++++++++ 10 files changed, 103 insertions(+), 13 deletions(-) diff --git a/apps/contracts/openapi.json b/apps/contracts/openapi.json index f36d7a18d4..58e5450684 100644 --- a/apps/contracts/openapi.json +++ b/apps/contracts/openapi.json @@ -1814,7 +1814,9 @@ "enum": [ "default", "plan", - "acceptEdits" + "acceptEdits", + "auto", + "yolo" ] }, "model": { @@ -2991,7 +2993,9 @@ "enum": [ "default", "plan", - "acceptEdits" + "acceptEdits", + "auto", + "yolo" ] } }, diff --git a/apps/contracts/src/generated/types.gen.ts b/apps/contracts/src/generated/types.gen.ts index 21bdb3ad16..01c7927f99 100644 --- a/apps/contracts/src/generated/types.gen.ts +++ b/apps/contracts/src/generated/types.gen.ts @@ -702,7 +702,7 @@ export type GetSessionDetailResponses = { }; id: string; kind: string; - mode: 'default' | 'plan' | 'acceptEdits'; + mode: 'default' | 'plan' | 'acceptEdits' | 'auto' | 'yolo'; model?: { id: string; providerId: string; @@ -1033,7 +1033,7 @@ export type SetSessionModeResponses = { * The authoritative session permission mode. */ 200: { - mode: 'default' | 'plan' | 'acceptEdits'; + mode: 'default' | 'plan' | 'acceptEdits' | 'auto' | 'yolo'; }; }; diff --git a/apps/contracts/src/schemas/chat.ts b/apps/contracts/src/schemas/chat.ts index 75737fddc8..aa391e5d06 100644 --- a/apps/contracts/src/schemas/chat.ts +++ b/apps/contracts/src/schemas/chat.ts @@ -4,6 +4,12 @@ import { z } from "zod"; export const sessionModeSchema = z.enum(["default", "plan", "acceptEdits"]); +/** + * A session's reported mode. It adds the autonomous modes a session created + * outside Studio can run in; Studio reads them but never requests them. + */ +export const sessionReportedModeSchema = z.enum(["default", "plan", "acceptEdits", "auto", "yolo"]); + export const sessionToolAccessSchema = z.enum(["all", "noFilesystem"]); export const reasoningEffortSchema = z.enum(["default", "low", "medium", "high", "xhigh", "max"]); @@ -123,7 +129,7 @@ export const sessionDetailResponseSchema = z.object({ }), id: z.string(), kind: z.string(), - mode: sessionModeSchema, + mode: sessionReportedModeSchema, model: sessionModelSelectionSchema .extend({ contextWindow: z.string(), @@ -155,7 +161,7 @@ export const setSessionModeRequestSchema = z.object({ }); export const setSessionModeResponseSchema = z.object({ - mode: sessionModeSchema, + mode: sessionReportedModeSchema, }); export const forkSessionRequestSchema = z.object({ diff --git a/apps/server/src/mecatl/chat.test.ts b/apps/server/src/mecatl/chat.test.ts index c6a1fe8996..7a8b7f6bc3 100644 --- a/apps/server/src/mecatl/chat.test.ts +++ b/apps/server/src/mecatl/chat.test.ts @@ -517,6 +517,30 @@ describe("Mecatl chat sessions", () => { }); }); + it("reports an autonomous session's mode instead of folding it into default", async () => { + // A session created elsewhere in auto or yolo must not read as Manual. + for (const [mode, want] of [ + [SessionMode.Auto, "auto"], + [SessionMode.Yolo, "yolo"], + ] as const) { + const snapshot = vi.fn().mockResolvedValue({ + sessionId: "session-1", + state: "idle", + mode, + tokenUsage: {}, + }); + const service = createMecatlChatService( + { sessions: { get: vi.fn().mockResolvedValue({ snapshot }) } } as unknown as Client, + () => + ({ + capabilities: { manualCompaction: false, modelSelection: true }, + }) as ServerCompatibility, + ); + + await expect(service.detail("session-1")).resolves.toMatchObject({ mode: want }); + } + }); + it("keeps the resolved model's fields for a provider with no display name", async () => { // Pins the session model served before provider display names (#2260). const snapshot = vi.fn().mockResolvedValue({ diff --git a/apps/server/src/mecatl/chat.ts b/apps/server/src/mecatl/chat.ts index 8be1abb6e7..cbe6fe6b7e 100644 --- a/apps/server/src/mecatl/chat.ts +++ b/apps/server/src/mecatl/chat.ts @@ -112,7 +112,7 @@ export interface ChatService { setMode( sessionId: string, mode: CreateSessionRequest["mode"], - ): Promise<{ mode: CreateSessionRequest["mode"] }>; + ): Promise<{ mode: SessionDetailResponse["mode"] }>; transcript(sessionId: string, signal?: AbortSignal): Promise; } @@ -609,9 +609,13 @@ function toSessionMode(mode: CreateSessionRequest["mode"]) { return SessionMode.Default; } -function fromSessionMode(mode: SessionMode): CreateSessionRequest["mode"] { +// Auto and yolo are kept, not folded into default: a session created elsewhere +// in an autonomous mode must not read as one that asks before every change. +function fromSessionMode(mode: SessionMode): SessionDetailResponse["mode"] { if (mode === SessionMode.Plan) return "plan"; if (mode === SessionMode.AcceptEdits) return "acceptEdits"; + if (mode === SessionMode.Auto) return "auto"; + if (mode === SessionMode.Yolo) return "yolo"; return "default"; } diff --git a/apps/web/src/features/chat/chat-composer.alignment.test.tsx b/apps/web/src/features/chat/chat-composer.alignment.test.tsx index f2eae5dd7b..768e720f77 100644 --- a/apps/web/src/features/chat/chat-composer.alignment.test.tsx +++ b/apps/web/src/features/chat/chat-composer.alignment.test.tsx @@ -10,6 +10,7 @@ import { reconcileAccount, } from "../../lib/account-storage"; import { readDraft, writeDraft } from "../../lib/draft-store"; +import { isSelectableMode } from "../../lib/permission-mode"; import { ShortcutProvider, useShortcut } from "../shortcuts/shortcut-provider"; import { ChatComposer, type DraftChatConfiguration } from "./chat-composer"; import { composerFrameClass } from "./composer-frame"; @@ -801,6 +802,24 @@ describe("PermissionModeBadge", () => { view.rerender(); expect(view.container.textContent).toBe("Permission mode: Plan"); }); + + it("names an autonomous mode set outside Studio instead of hiding it as Manual", () => { + const view = render(); + expect(view.container.textContent).toBe("Permission mode: Auto"); + view.rerender(); + expect(view.container.textContent).toBe("Permission mode: YOLO"); + }); +}); + +describe("isSelectableMode", () => { + it("offers the Mode control only for the modes Studio can set", () => { + expect( + ["default", "plan", "acceptEdits"].every((mode) => isSelectableMode(mode as never)), + ).toBe(true); + expect(isSelectableMode("auto")).toBe(false); + expect(isSelectableMode("yolo")).toBe(false); + expect(isSelectableMode(undefined)).toBe(false); + }); }); describe("QueuedMessageStrip", () => { diff --git a/apps/web/src/features/chat/chat-workspace.tsx b/apps/web/src/features/chat/chat-workspace.tsx index 0102fa8ca7..d45b8d4b18 100644 --- a/apps/web/src/features/chat/chat-workspace.tsx +++ b/apps/web/src/features/chat/chat-workspace.tsx @@ -103,6 +103,7 @@ import { notifyRunCompletion } from "../../lib/browser-notifications"; import { copyToClipboard } from "../../lib/clipboard"; import { errorMessage } from "../../lib/error-message"; import { modelPreferenceId, useDisabledModels } from "../../lib/model-preferences"; +import { isSelectableMode, modeTitle } from "../../lib/permission-mode"; import { defaultAgentName, useAgentAvatar, @@ -1004,7 +1005,9 @@ export function ChatWorkspace({ sessionId }: { sessionId?: string }) { ? "Plan" : seedMode === "acceptEdits" ? "Accept edits" - : "Loading permission mode", + : seedMode === "auto" || seedMode === "yolo" + ? `${modeTitle(seedMode)} (set outside Studio)` + : "Loading permission mode", execution: sessionId ? displayedDetail ? `Files: ${displayedDetail.capabilities.executionFiles ? "available" : "unavailable"}; built-in Shell: ${displayedDetail.capabilities.builtInShell ? "available" : "unavailable"}` @@ -3492,7 +3495,11 @@ export function ChatWorkspace({ sessionId }: { sessionId?: string }) { draftKey={sessionId ?? "new"} imageAttachmentsSupported={imageAttachmentsSupported} liveControlsDisabled={liveControlsDisabled} - liveMode={sessionId ? displayedDetail?.mode : undefined} + liveMode={ + sessionId && isSelectableMode(displayedDetail?.mode) + ? displayedDetail.mode + : undefined + } liveModel={sessionId ? displayedDetail?.model : undefined} models={models} onConfigurationChange={setDraftConfiguration} diff --git a/apps/web/src/features/chat/permission-mode-badge.tsx b/apps/web/src/features/chat/permission-mode-badge.tsx index ebdc9bbee2..5358a82715 100644 --- a/apps/web/src/features/chat/permission-mode-badge.tsx +++ b/apps/web/src/features/chat/permission-mode-badge.tsx @@ -1,21 +1,29 @@ // SPDX-License-Identifier: Apache-2.0 import { Badge } from "../../components/ui/badge"; -import { modeTitle, type SessionPermissionMode } from "../../lib/permission-mode"; +import { modeTitle, type SessionReportedMode } from "../../lib/permission-mode"; /** * The chat header's permission-mode badge, from the prototype (`stack-08`). * It is silent for Manual, the everyday posture, so a badge in the header * always means the chat does not ask before every change. */ -export function PermissionModeBadge({ mode }: { mode?: SessionPermissionMode }) { +export function PermissionModeBadge({ mode }: { mode?: SessionReportedMode }) { if (!mode || mode === "default") return null; const label = modeTitle(mode); return ( Permission mode: {label} diff --git a/apps/web/src/features/chat/session-details-dialog.tsx b/apps/web/src/features/chat/session-details-dialog.tsx index 39678378a5..ceed82ced0 100644 --- a/apps/web/src/features/chat/session-details-dialog.tsx +++ b/apps/web/src/features/chat/session-details-dialog.tsx @@ -51,8 +51,10 @@ const PROVENANCE_LABEL: Record = { const MODE_LABEL: Record = { acceptEdits: "Accept edits", + auto: "Auto", default: "Default", plan: "Plan", + yolo: "YOLO", }; /** A no-filesystem session's placement kinds. */ diff --git a/apps/web/src/lib/permission-mode.ts b/apps/web/src/lib/permission-mode.ts index 241553b387..5ea3ba684c 100644 --- a/apps/web/src/lib/permission-mode.ts +++ b/apps/web/src/lib/permission-mode.ts @@ -3,6 +3,20 @@ /** Mirrors `sessionModeSchema` in `contracts/src/schemas/chat.ts`. */ export type SessionPermissionMode = "acceptEdits" | "default" | "plan"; +/** + * Mirrors `sessionReportedModeSchema`: what a live chat reports. Auto and yolo + * come from a chat created outside Studio. Studio shows them but cannot set + * them, so a chat in either has no Mode control here. + */ +export type SessionReportedMode = SessionPermissionMode | "auto" | "yolo"; + +/** Whether Studio's Mode control can show and change this mode. */ +export function isSelectableMode( + mode: SessionReportedMode | undefined, +): mode is SessionPermissionMode { + return mode === "default" || mode === "plan" || mode === "acceptEdits"; +} + export interface PermissionModeOption { description: string; /** The posture dot before the title: none for Manual, green for Accept edits, blue for Plan. */ @@ -39,5 +53,7 @@ export const MODE_OPTIONS: PermissionModeOption[] = [ ]; export function modeTitle(mode: string | undefined): string { + if (mode === "auto") return "Auto"; + if (mode === "yolo") return "YOLO"; return MODE_OPTIONS.find((option) => option.value === mode)?.title ?? "Manual"; } From de36b07abc93fc2d6a8d069f8a0aab5c06073d5b Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:33:00 +0300 Subject: [PATCH 34/48] fix(helm): reject single-dash mode flags in extraArgs The extraArgs guard only matched double-dash prefixes, but Go's flag parser also accepts single-dash long flags. -permission-mode=yolo could replace the chart-generated mode, and -posture=strict reached a runtime conflict instead of the render-time migration error. Match one or two leading dashes with the exact flag name, in both the "=" and split-argument forms. Co-Authored-By: Claude Opus 5.5 --- deploy/helm/mecak8s/chart_test.go | 7 +++++++ deploy/helm/mecak8s/templates/_helpers.tpl | 3 ++- deploy/helm/mecak8s/values.yaml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/deploy/helm/mecak8s/chart_test.go b/deploy/helm/mecak8s/chart_test.go index a7b53dd611..fed35dd3ae 100644 --- a/deploy/helm/mecak8s/chart_test.go +++ b/deploy/helm/mecak8s/chart_test.go @@ -3135,6 +3135,13 @@ func TestPermissionModeValuesAreValidated(t *testing.T) { {name: "split posture in extraArgs", extra: []string{"--set", "extraArgs[0]=--posture,extraArgs[1]=auto"}, want: []string{"--posture", "permissionMode"}}, {name: "permission-mode in extraArgs", extra: []string{"--set", "extraArgs[0]=--permission-mode=yolo"}, want: []string{"--permission-mode=yolo", "permissionMode"}}, {name: "yolo in extraArgs", extra: []string{"--set", "extraArgs[0]=--yolo"}, want: []string{"--yolo", "permissionMode"}}, + // Go's flag parser also accepts single-dash long flags. + {name: "single-dash posture in extraArgs", extra: []string{"--set", "extraArgs[0]=-posture=strict"}, want: []string{"-posture=strict", "permissionMode"}}, + {name: "single-dash split posture in extraArgs", extra: []string{"--set", "extraArgs[0]=-posture,extraArgs[1]=strict"}, want: []string{"-posture", "permissionMode"}}, + {name: "single-dash permission-mode in extraArgs", extra: []string{"--set", "extraArgs[0]=-permission-mode=yolo"}, want: []string{"-permission-mode=yolo", "permissionMode"}}, + {name: "single-dash split permission-mode in extraArgs", extra: []string{"--set", "extraArgs[0]=-permission-mode,extraArgs[1]=yolo"}, want: []string{"-permission-mode", "permissionMode"}}, + {name: "split permission-mode in extraArgs", extra: []string{"--set", "extraArgs[0]=--permission-mode,extraArgs[1]=yolo"}, want: []string{"--permission-mode", "permissionMode"}}, + {name: "single-dash yolo in extraArgs", extra: []string{"--set", "extraArgs[0]=-yolo"}, want: []string{"-yolo", "permissionMode"}}, {name: "model and disabled", extra: []string{"--set", "guardrails.model=checker,guardrails.disabled=true"}, want: []string{"guardrails.model", "guardrails.disabled"}}, } for _, tc := range cases { diff --git a/deploy/helm/mecak8s/templates/_helpers.tpl b/deploy/helm/mecak8s/templates/_helpers.tpl index a4294905b1..638bf3ae5f 100644 --- a/deploy/helm/mecak8s/templates/_helpers.tpl +++ b/deploy/helm/mecak8s/templates/_helpers.tpl @@ -163,7 +163,8 @@ mounted {{- end -}} {{- range $arg := .Values.extraArgs -}} {{- $a := toString $arg -}} -{{- if or (hasPrefix "--posture" $a) (hasPrefix "--permission-mode" $a) (hasPrefix "--yolo" $a) -}} +{{- /* Go's flag parser accepts one or two leading dashes, with the value after "=" or in the next argument. */ -}} +{{- if regexMatch "^--?(posture|permission-mode|yolo)(=|$)" $a -}} {{- fail (printf "extraArgs entry %q sets the permission mode, which the chart owns; remove it and set permissionMode instead (--posture=strict becomes permissionMode: default, --posture=auto becomes permissionMode: auto, --posture=yolo or --yolo becomes permissionMode: yolo)" $a) -}} {{- end -}} {{- end -}} diff --git a/deploy/helm/mecak8s/values.yaml b/deploy/helm/mecak8s/values.yaml index 0dfddf034b..8720b0f7f5 100644 --- a/deploy/helm/mecak8s/values.yaml +++ b/deploy/helm/mecak8s/values.yaml @@ -38,7 +38,7 @@ logging: # the escape hatch for flags not modeled by the chart; when it contains --log-level, # it is appended after logging.level and therefore takes precedence. The chart owns # the permission mode: rendering fails if extraArgs sets --posture, -# --permission-mode, or --yolo; set permissionMode instead. +# --permission-mode, or --yolo (with one or two dashes); set permissionMode instead. extraArgs: [] # First-class remote Streamable HTTP MCP connections. Authentication is an From f110d68790509c5d2974dd7ef3c58f2be3486bb7 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:34:00 +0300 Subject: [PATCH 35/48] fix(helm): enumerate permissionMode values in the chart schema The schema typed permissionMode as any string, so editors and `helm lint` could not flag a typo until the template's own check failed at render time. List the five permission modes in the schema enum; the template check stays as the fallback for renders that skip schema validation. Co-Authored-By: Claude Opus 5.5 --- deploy/helm/mecak8s/chart_test.go | 3 ++- deploy/helm/mecak8s/values.schema.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/deploy/helm/mecak8s/chart_test.go b/deploy/helm/mecak8s/chart_test.go index fed35dd3ae..1d98c9ac86 100644 --- a/deploy/helm/mecak8s/chart_test.go +++ b/deploy/helm/mecak8s/chart_test.go @@ -3130,7 +3130,8 @@ func TestPermissionModeValuesAreValidated(t *testing.T) { extra []string want []string }{ - {name: "unknown mode", extra: []string{"--set", "permissionMode=trusted"}, want: []string{"permissionMode", "plan, default, accept-edits, auto, yolo"}}, + // The schema enum rejects it first; its message format varies by Helm version. + {name: "unknown mode", extra: []string{"--set", "permissionMode=trusted"}, want: []string{"permissionMode", "accept-edits"}}, {name: "posture in extraArgs", extra: []string{"--set", "extraArgs[0]=--posture=strict"}, want: []string{"--posture=strict", "permissionMode"}}, {name: "split posture in extraArgs", extra: []string{"--set", "extraArgs[0]=--posture,extraArgs[1]=auto"}, want: []string{"--posture", "permissionMode"}}, {name: "permission-mode in extraArgs", extra: []string{"--set", "extraArgs[0]=--permission-mode=yolo"}, want: []string{"--permission-mode=yolo", "permissionMode"}}, diff --git a/deploy/helm/mecak8s/values.schema.json b/deploy/helm/mecak8s/values.schema.json index 7dd1028ab0..677e264b1f 100644 --- a/deploy/helm/mecak8s/values.schema.json +++ b/deploy/helm/mecak8s/values.schema.json @@ -107,7 +107,7 @@ "disabled": {"type": "boolean"} } }, - "permissionMode": {"type": "string"}, + "permissionMode": {"type": "string", "enum": ["plan", "default", "accept-edits", "auto", "yolo"]}, "telemetry": { "type": "object", "additionalProperties": false, From 16b79e271198dd0b45f613026ee21b9cfa826227 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:34:46 +0300 Subject: [PATCH 36/48] docs(ci): match the reusable mecatequi reviewer note to the action default The reusable workflow's opening comment still described subagent-ask-reviewer as an opt-in autonomous-approval capability. The action now turns the reviewer on by default in the auto and yolo modes, and the reusable workflow runs the action's default auto mode, so its callers get the reviewer. Say so, and keep the note that choosing another reviewer or "off" is made by editing the action. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/mecatequi-reusable.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mecatequi-reusable.yml b/.github/workflows/mecatequi-reusable.yml index f9ad728132..4b8ee4980e 100644 --- a/.github/workflows/mecatequi-reusable.yml +++ b/.github/workflows/mecatequi-reusable.yml @@ -13,9 +13,11 @@ on: # Inputs are the per-session passthrough surface of the mecatequi action. The # escape-hatch-only knobs are deliberately NOT exposed here — `default-model` (catalog- # validated, rejects an uncatalogued id — use `model` instead), `openai` (provider is - # auto-detected from the present key), and `subagent-ask-reviewer` (an autonomous-approval - # capability that is a deployment decision better made by editing the action) — so a - # consumer needing them vendors the escape-hatch template rather than the reusable workflow. + # auto-detected from the present key), and `subagent-ask-reviewer` (the action default + # applies: under its default auto permission mode the reviewer is ON, using the ask-reviewer + # model slot or else the session model; choosing another reviewer or "off" is a deployment + # decision better made by editing the action) — so a consumer needing them vendors the + # escape-hatch template rather than the reusable workflow. inputs: label: description: >- From 639385fcafb86f712540a7226d296085f6324b67 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:26:20 +0300 Subject: [PATCH 37/48] fix(permissions): keep explicit default child modes and re-admit resumed children An omitted child mode and an explicit WithChildMode/WithParallelChildMode( ModeDefault) or member permissionMode: default were indistinguishable, so both inherited an auto or yolo parent and dropped default's builtin asks and, under yolo, its substitution checkpoint. Empty is now the inherit sentinel and any explicit mode, default included, is kept; an unknown member permissionMode pins default rather than inheriting. A resumed Subagent child also kept the mode it was persisted with, so a child created under a yolo parent retained yolo's authority after the parent was downgraded or the ceiling tightened. Both resume paths now run the child in the narrower of its stored mode and the mode a fresh child of the current parent would get, before it executes or is re-persisted, with its history untouched. Co-Authored-By: Claude Opus 5.5 --- engine/CHANGELOG.md | 14 +- engine/agent/child_mode_inherit_test.go | 186 +++++++++++++++++++++++- engine/agent/export_test.go | 3 + engine/agent/parallel.go | 12 +- engine/agent/subagent.go | 75 ++++++++-- engine/agent/teamtool.go | 5 +- internal/app/agentdefs.go | 14 +- internal/app/agentdefs_test.go | 21 +++ 8 files changed, 288 insertions(+), 42 deletions(-) diff --git a/engine/CHANGELOG.md b/engine/CHANGELOG.md index d2c7c6e8ab..681c044fab 100644 --- a/engine/CHANGELOG.md +++ b/engine/CHANGELOG.md @@ -450,12 +450,14 @@ The covered surface is the eight core packages (`session`, `governance`, `learni wire clients are unaffected. - **Delegated children inherit an auto or yolo parent's mode** — a Subagent - child, Parallel branch, or Team member whose configured mode is the default - (`ModeDefault`) now runs in its parent session's mode when that mode is - `ModeAuto` or `ModeYolo`, so the parent's mode-driven authority reaches its - delegates. An explicitly configured narrower mode (`WithChildMode`, - `WithParallelChildMode`, `WithTeamMode`, or a member definition's - `permissionMode`) is kept. No signature changes. + child, Parallel branch, or Team member with no configured mode now runs in its + parent session's mode when that mode is `ModeAuto` or `ModeYolo`, so the + parent's mode-driven authority reaches its delegates. Any explicitly + configured mode (`WithChildMode`, `WithParallelChildMode`, `WithTeamMode`, or + a member definition's `permissionMode`), `ModeDefault` included, is kept. A + resumed Subagent child's persisted mode is re-admitted against the current + parent: it runs in the narrower of its stored mode and the mode a fresh child + would get. No signature changes. - **Atomic one-shot retry eligibility (issue #2273)** — `port.ScheduleOneShotReArmer.ReArmOneShot` now requires store-side atomic diff --git a/engine/agent/child_mode_inherit_test.go b/engine/agent/child_mode_inherit_test.go index 1332145d39..8128695b3a 100644 --- a/engine/agent/child_mode_inherit_test.go +++ b/engine/agent/child_mode_inherit_test.go @@ -2,10 +2,12 @@ package agent_test 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/permpolicy" "github.com/stacklok/mecatl/engine/agent" @@ -13,18 +15,20 @@ import ( "github.com/stacklok/mecatl/engine/tool" ) -// TestEffectiveChildMode pins the inheritance table: a default-configured child -// inherits an auto or yolo parent; other parents and explicitly configured -// child modes are kept. +// TestEffectiveChildMode pins the inheritance table: an unconfigured child +// inherits an auto or yolo parent and otherwise runs in default; every +// explicitly configured child mode, default included, is kept. func TestEffectiveChildMode(t *testing.T) { for _, tc := range []struct { configured, parent, want session.PermissionMode }{ - {session.ModeDefault, session.ModeYolo, session.ModeYolo}, - {session.ModeDefault, session.ModeAuto, session.ModeAuto}, - {session.ModeDefault, session.ModeAccept, session.ModeDefault}, - {session.ModeDefault, session.ModePlan, session.ModeDefault}, - {session.ModeDefault, "", session.ModeDefault}, + {"", session.ModeYolo, session.ModeYolo}, + {"", session.ModeAuto, session.ModeAuto}, + {"", session.ModeAccept, session.ModeDefault}, + {"", session.ModePlan, session.ModeDefault}, + {"", "", session.ModeDefault}, + {session.ModeDefault, session.ModeYolo, session.ModeDefault}, + {session.ModeDefault, session.ModeAuto, session.ModeDefault}, {session.ModePlan, session.ModeYolo, session.ModePlan}, {session.ModeAccept, session.ModeAuto, session.ModeAccept}, } { @@ -84,3 +88,169 @@ func TestSubagentInheritsYoloParentMode(t *testing.T) { } } } + +// mutatingChildEngine builds a child engine whose only tool mutates and asks +// under the default mode (no rules, headless → denied), counting executions. +func mutatingChildEngine(t *testing.T, executed *atomic.Int32, turns ...mockllm.Turn) *agent.Engine { + t.Helper() + childTool := &fakeTool{name: "Mutate", readOnly: false, + exec: func(_ context.Context, in session.ToolCall, _ tool.Workspace) (session.ToolResult, error) { + executed.Add(1) + return session.NewToolResult(in.ID, "ran"), nil + }} + return agent.NewEngine(agent.Deps{ + LLM: mockllm.New(turns...), + Catalog: catalogWith(t, childTool), + Policy: permpolicy.NewPolicy(nil, nil), + Model: "child-model", + }) +} + +// runParent drives one parent run in mode to completion and returns its events. +func runParent(t *testing.T, sess *session.Session, mode session.PermissionMode, parentLLM *mockllm.Provider, tools ...tool.Tool) []session.Event { + t.Helper() + if sess.State == session.StateCompleted { + if err := sess.Reopen(); err != nil { + t.Fatal(err) + } + } + if err := sess.SetMode(mode); err != nil { + t.Fatal(err) + } + e := newEngine(agent.Deps{LLM: parentLLM, Catalog: catalogWith(t, tools...)}) + return drainObserving(t, e.Run(context.Background(), sess, agent.MemEnv("/ws"), agent.RunRequest{Text: "go"}), nil) +} + +// TestExplicitDefaultChildModeIsKeptUnderYoloParent proves an explicitly +// configured default mode is a restriction, not "inherit": fresh foreground +// and background Subagent children and Parallel branches keep default's ask +// (headless → denied) under a yolo parent, while unconfigured ones inherit yolo. +func TestExplicitDefaultChildModeIsKeptUnderYoloParent(t *testing.T) { + childTurns := func() []mockllm.Turn { + return []mockllm.Turn{mockllm.ToolCallTurn(toolCall("k1", "Mutate", `{}`)), mockllm.TextTurn("child done")} + } + for _, tc := range []struct { + name string + explicit bool + build func(*agent.Engine) tool.Tool + parent []mockllm.Turn + }{ + {"subagent", true, func(e *agent.Engine) tool.Tool { + return agent.NewSubagentTool(e, agent.WithChildMode(session.ModeDefault)) + }, + []mockllm.Turn{mockllm.ToolCallTurn(toolCall("p1", "Subagent", `{"prompt":"go"}`)), mockllm.TextTurn("ok")}}, + {"subagent-inherit", false, func(e *agent.Engine) tool.Tool { return agent.NewSubagentTool(e) }, + []mockllm.Turn{mockllm.ToolCallTurn(toolCall("p1", "Subagent", `{"prompt":"go"}`)), mockllm.TextTurn("ok")}}, + {"subagent-background", true, func(e *agent.Engine) tool.Tool { + return agent.NewSubagentTool(e, agent.WithChildMode(session.ModeDefault)) + }, + []mockllm.Turn{ + mockllm.ToolCallTurn(toolCall("p1", "Subagent", `{"prompt":"go","background":true}`)), + mockllm.ToolCallTurn(toolCall("p2", "SubagentStatus", `{"agent_id":"subagent-s1-p1","wait_ms":30000}`)), + mockllm.TextTurn("ok"), + }}, + {"parallel", true, func(e *agent.Engine) tool.Tool { + return agent.NewParallelTool(e, &memForker{}, agent.WithParallelChildMode(session.ModeDefault)) + }, []mockllm.Turn{mockllm.ToolCallTurn(toolCall("p1", "Parallel", `{"tasks":["A"]}`)), mockllm.TextTurn("ok")}}, + {"parallel-inherit", false, func(e *agent.Engine) tool.Tool { return agent.NewParallelTool(e, &memForker{}) }, + []mockllm.Turn{mockllm.ToolCallTurn(toolCall("p1", "Parallel", `{"tasks":["A"]}`)), mockllm.TextTurn("ok")}}, + } { + t.Run(tc.name, func(t *testing.T) { + var executed atomic.Int32 + delegate := tc.build(mutatingChildEngine(t, &executed, childTurns()...)) + runParent(t, newSession(t, session.Limits{}), session.ModeYolo, mockllm.New(tc.parent...), delegate, agent.NewSubagentStatusTool()) + if got, want := executed.Load() == 1, !tc.explicit; got != want { + t.Errorf("child mutating tool executed=%t under a yolo parent, want %t", got, want) + } + }) + } +} + +// TestResumedSubagentReadmitsModeAfterParentDowngrade proves a child persisted +// under a yolo parent does not keep yolo's authority when it is resumed, after a +// restart, by a parent that has since been downgraded to default. Both the +// foreground and the background resume paths re-admit the stored mode before +// the child runs; the child's history is preserved. +func TestResumedSubagentReadmitsModeAfterParentDowngrade(t *testing.T) { + for _, background := range []bool{false, true} { + name := "foreground" + if background { + name = "background" + } + t.Run(name, func(t *testing.T) { + store := memstore.New() + var executed atomic.Int32 + sess := newSession(t, session.Limits{}) + + // Phase 1: the yolo parent creates the child, whose mutation runs. + first := agent.NewSubagentTool(mutatingChildEngine(t, &executed, + mockllm.ToolCallTurn(toolCall("k1", "Mutate", `{}`)), mockllm.TextTurn("FIRST_PASS")), + agent.WithSubagentStore(store)) + runParent(t, sess, session.ModeYolo, mockllm.New( + mockllm.ToolCallTurn(toolCall("p1", "Subagent", `{"prompt":"go"}`)), mockllm.TextTurn("ok")), first) + if executed.Load() != 1 { + t.Fatalf("yolo parent: child mutation executed %d times, want 1", executed.Load()) + } + if stored, err := store.Load(context.Background(), "subagent-s1-p1"); err != nil || stored.Mode != session.ModeYolo { + t.Fatalf("persisted child = %v, %v; want mode yolo", stored, err) + } + + // Phase 2: a restarted harness (fresh tool and engines, same store) + // resumes the child from a parent downgraded to default. + second := agent.NewSubagentTool(mutatingChildEngine(t, &executed, + mockllm.ToolCallTurn(toolCall("k2", "Mutate", `{}`)), mockllm.TextTurn("SECOND_PASS")), + agent.WithSubagentStore(store)) + parentTurns := []mockllm.Turn{mockllm.ToolCallTurn(toolCall("p2", "Subagent", `{"prompt":"again","resume":"subagent-s1-p1"}`)), mockllm.TextTurn("ok")} + collect := session.ToolCallID("p2") + if background { + parentTurns = []mockllm.Turn{ + mockllm.ToolCallTurn(toolCall("p2", "Subagent", `{"prompt":"again","resume":"subagent-s1-p1","background":true}`)), + mockllm.ToolCallTurn(toolCall("p3", "SubagentStatus", `{"agent_id":"subagent-s1-p1","wait_ms":30000}`)), + mockllm.TextTurn("ok"), + } + collect = "p3" + } + evs := runParent(t, sess, session.ModeDefault, mockllm.New(parentTurns...), second, agent.NewSubagentStatusTool()) + if res := resultByCallID(evs)[collect]; res == nil || !strings.Contains(res.Content, "SECOND_PASS") { + t.Fatalf("resumed child did not complete: %+v; events %v; state %s", res, typesOf(evs), sess.State) + } + if executed.Load() != 1 { + t.Errorf("downgraded parent: resumed child kept yolo authority (mutation executed %d times, want 1)", executed.Load()) + } + stored, err := store.Load(context.Background(), "subagent-s1-p1") + if err != nil { + t.Fatal(err) + } + if stored.Mode != session.ModeDefault { + t.Errorf("re-persisted child mode = %q, want %q", stored.Mode, session.ModeDefault) + } + var kept bool + for _, m := range stored.Conversation.Messages { + kept = kept || strings.Contains(m.Text, "FIRST_PASS") + } + if !kept { + t.Error("resumed child lost its prior history") + } + }) + } +} + +// TestResumedChildMode pins the re-admission table: the narrower of the stored +// mode and what a fresh child of the current parent would get. +func TestResumedChildMode(t *testing.T) { + for _, tc := range []struct { + stored, configured, parent, want session.PermissionMode + }{ + {session.ModeYolo, "", session.ModeDefault, session.ModeDefault}, + {session.ModeYolo, "", session.ModeAuto, session.ModeAuto}, + {session.ModeYolo, "", session.ModeYolo, session.ModeYolo}, + {session.ModeAuto, "", session.ModeYolo, session.ModeAuto}, + {session.ModeDefault, "", session.ModeYolo, session.ModeDefault}, + {session.ModePlan, "", session.ModeYolo, session.ModePlan}, + {session.ModeYolo, session.ModeAccept, session.ModeYolo, session.ModeAccept}, + } { + if got := agent.ResumedChildModeForTest(tc.stored, tc.configured, tc.parent); got != tc.want { + t.Errorf("resumedChildMode(stored %q, configured %q, parent %q) = %q, want %q", tc.stored, tc.configured, tc.parent, got, tc.want) + } + } +} diff --git a/engine/agent/export_test.go b/engine/agent/export_test.go index 6ccf375445..559ba0ee7a 100644 --- a/engine/agent/export_test.go +++ b/engine/agent/export_test.go @@ -39,3 +39,6 @@ func WithParallelBranchRegisteredForTest(fn func(int)) ParallelOption { // EffectiveChildModeForTest exposes the delegated-child mode rule. var EffectiveChildModeForTest = effectiveChildMode + +// ResumedChildModeForTest exposes the resumed-child mode re-admission rule. +var ResumedChildModeForTest = resumedChildMode diff --git a/engine/agent/parallel.go b/engine/agent/parallel.go index 3851605157..5245b0a490 100644 --- a/engine/agent/parallel.go +++ b/engine/agent/parallel.go @@ -139,8 +139,8 @@ type ParallelTool struct { // limits bound a single child branch run. Defaults to defaultChildLimits. limits session.Limits - // childMode is the permission mode each child session runs under. Defaults to - // session.ModeDefault. + // childMode is the permission mode each child session runs under. Empty (the + // default) inherits the parent's mode; see effectiveChildMode. childMode session.PermissionMode // maxBranches caps the fan-out per Parallel call. @@ -210,9 +210,10 @@ func WithParallelChildLimits(l session.Limits) ParallelOption { return func(t *ParallelTool) { t.limits = l } } -// WithParallelChildMode sets the permission mode each child branch session runs under -// (default session.ModeDefault, which inherits an auto or yolo parent's mode; see -// effectiveChildMode). +// WithParallelChildMode sets the permission mode each child branch session runs under. +// Without it a branch inherits an auto or yolo parent's mode and otherwise runs in +// session.ModeDefault (see effectiveChildMode); an explicit session.ModeDefault keeps +// default even under an auto or yolo parent. func WithParallelChildMode(m session.PermissionMode) ParallelOption { return func(t *ParallelTool) { t.childMode = m } } @@ -335,7 +336,6 @@ func NewParallelTool(childEngine *Engine, forker tool.EnvironmentForker, opts .. childEngine: childEngine, forker: forker, limits: defaultChildLimits, - childMode: session.ModeDefault, maxBranches: defaultMaxBranches, concurrency: defaultParallelConcurrency, idPrefix: strings.TrimSuffix(ParallelSessionPrefix, "-"), // the exported convention is the source diff --git a/engine/agent/subagent.go b/engine/agent/subagent.go index db3a1e74a6..3838b500fe 100644 --- a/engine/agent/subagent.go +++ b/engine/agent/subagent.go @@ -683,8 +683,8 @@ type SubagentTool struct { // limits bound a single child run. Defaults to defaultChildLimits. limits session.Limits - // childMode is the permission mode the child session runs under. Defaults to - // session.ModeDefault. + // childMode is the permission mode the child session runs under. Empty (the + // default) inherits the parent's mode; see effectiveChildMode. childMode session.PermissionMode // hooks fires the SubagentStop lifecycle hook when a child finishes @@ -1016,25 +1016,62 @@ func WithChildLimits(l session.Limits) SubagentOption { return func(t *SubagentTool) { t.limits = l } } -// WithChildMode sets the permission mode the child session runs under (default -// session.ModeDefault, which inherits an auto or yolo parent's mode; see -// effectiveChildMode). session.ModePlan additionally hides any non-read-only -// tools from the child at the catalog level. +// WithChildMode sets the permission mode the child session runs under. Without +// it the child inherits an auto or yolo parent's mode and otherwise runs in +// session.ModeDefault (see effectiveChildMode); an explicit session.ModeDefault +// keeps default even under an auto or yolo parent. session.ModePlan additionally +// hides any non-read-only tools from the child at the catalog level. func WithChildMode(m session.PermissionMode) SubagentOption { return func(t *SubagentTool) { t.childMode = m } } // effectiveChildMode is the mode a delegated child session runs in. A child -// configured with the default mode inherits an auto or yolo parent's mode, so -// the parent's mode-driven authority (allow-all, and in yolo the loosened -// substitution floor) carries to its delegates; plan, default, and accept-edits -// parents keep the configured child mode. An explicitly narrower configured -// mode (for example plan) is never widened. +// with no configured mode ("") inherits an auto or yolo parent's mode, so the +// parent's mode-driven authority (allow-all, and in yolo the loosened +// substitution floor) carries to its delegates, and runs in session.ModeDefault +// under any other parent. Any explicitly configured mode, session.ModeDefault +// included, is kept. func effectiveChildMode(configured, parent session.PermissionMode) session.PermissionMode { - if configured == session.ModeDefault && (parent == session.ModeAuto || parent == session.ModeYolo) { + if configured != "" { + return configured + } + if parent == session.ModeAuto || parent == session.ModeYolo { return parent } - return configured + return session.ModeDefault +} + +// resumedChildMode re-admits a persisted child's mode against the mode a fresh +// child of the CURRENT parent would get: the narrower of the two in the +// plan < default < acceptEdits < auto < yolo order. A child created under a +// yolo parent therefore cannot keep yolo's authority after the parent (or the +// deployment ceiling that admitted the parent) tightens, while a stored mode +// that is already narrower is preserved. +func resumedChildMode(stored, configured, parent session.PermissionMode) session.PermissionMode { + admitted := effectiveChildMode(configured, parent) + if childModeRank(stored) <= childModeRank(admitted) { + return stored + } + return admitted +} + +// childModeRank orders permission modes by authority. An unknown mode ranks +// below plan, so it is never replaced by a wider one. +func childModeRank(mode session.PermissionMode) int { + switch mode { + case session.ModePlan: + return 1 + case session.ModeDefault: + return 2 + case session.ModeAccept: + return 3 + case session.ModeAuto: + return 4 + case session.ModeYolo: + return 5 + default: + return 0 + } } // WithSubagentStopHook injects the HookRunner that fires the SubagentStop hook @@ -1352,7 +1389,6 @@ func NewSubagentTool(childEngine *Engine, opts ...SubagentOption) tool.Tool { t := &SubagentTool{ childEngine: childEngine, limits: defaultChildLimits, - childMode: session.ModeDefault, idPrefix: strings.TrimSuffix(SubagentSessionPrefix, "-"), // the exported convention is the source inFlight: make(map[session.SessionID]struct{}), } @@ -4203,7 +4239,8 @@ func (t *SubagentTool) forkChildEnvironment(ctx context.Context, callID session. // stays consistent with where this run actually executes — the original worktree is // torn down, and without the re-home the re-persisted snapshot would record a dead // path. (The child's prompt cwd is independently sourced from the engine's PromptConfig -// and is NOT affected by this field.) +// and is NOT affected by this field.) A resumed child's persisted mode is also +// re-admitted against the current parent (resumedChildMode). func (t *SubagentTool) buildChildSession(callID session.ToolCallID, childID, parentID session.SessionID, parentIncarnation session.IncarnationID, parentMode session.PermissionMode, resumedChild *session.Session, env tool.Environment, limits session.Limits, forkHistory []session.Message, forkInstructions session.InstructionSnapshot) (*session.Session, session.ToolResult, bool) { if resumedChild == nil { // When a named agent def pins limits, the child runs under THOSE; otherwise it uses @@ -4242,6 +4279,14 @@ func (t *SubagentTool) buildChildSession(callID session.ToolCallID, childID, par return nil, session.NewToolError(callID, fmt.Sprintf("Subagent: failed to re-home resumed subagent %q: %v", childID, err)), false } + // Re-admit the persisted mode before the resumed child runs or is re-persisted + // (foreground and background resume both land here); history is untouched. + if mode := resumedChildMode(resumedChild.Mode, t.childMode, parentMode); mode != resumedChild.Mode { + if err := resumedChild.SetMode(mode); err != nil { + return nil, session.NewToolError(callID, + fmt.Sprintf("Subagent: failed to re-admit resumed subagent %q permission mode: %v", childID, err)), false + } + } return resumedChild, session.ToolResult{}, true } diff --git a/engine/agent/teamtool.go b/engine/agent/teamtool.go index 43f6483b43..09735a1b83 100644 --- a/engine/agent/teamtool.go +++ b/engine/agent/teamtool.go @@ -404,8 +404,9 @@ func (t *TeamTool) run(ctx context.Context, call session.ToolCall, env tool.Envi // is registered, persisted, or projected. opts = append(opts, withParentCaps(caps), withParentTeamCall(call.ID)) // Members of an auto or yolo parent inherit its mode (effectiveChildMode); a - // member definition's own permissionMode still overrides the team default. - if mode := effectiveChildMode(session.ModeDefault, caps.parentMode); mode != session.ModeDefault { + // member definition's own permissionMode, default included, still overrides + // the team default. + if mode := effectiveChildMode("", caps.parentMode); mode != session.ModeDefault { opts = append(opts, WithTeamMode(mode)) } sup := NewSupervisor(tm, env, factory, opts...) diff --git a/internal/app/agentdefs.go b/internal/app/agentdefs.go index 3a83b28d03..8662cb6c60 100644 --- a/internal/app/agentdefs.go +++ b/internal/app/agentdefs.go @@ -437,17 +437,21 @@ func lookupModelAlias(cfg Config, sel string) (id string, known bool) { // resolvePermissionMode maps a def's frontmatter permissionMode string to a // domain session.PermissionMode, in the composition layer (the domain never sees -// the raw string). "default"/empty/unknown => "" (the caller's default — for a team -// member that means the team-wide WithTeamMode). "plan" and "acceptEdits" map to -// their domain constants. An unrecognised value warns and falls back to the default. +// the raw string). Empty => "" (the caller's default — for a team member that +// means the team-wide WithTeamMode, which inherits an auto or yolo parent). +// "default", "plan", and "acceptEdits" map to their domain constants, so an +// explicit default stays default under an auto or yolo parent. An unrecognised +// value warns and falls back to session.ModeDefault rather than inheriting. // // Note (critique B2): plan mode hard-denies mutations (existing invariant), so a // plan member is effectively read-only even if Mutating. acceptEdits is meaningful // only for a Mutating member (a read-only member has no mutating tools to accept). func resolvePermissionMode(d port.Diagnostics, def agents.AgentDef) session.PermissionMode { switch strings.TrimSpace(def.PermissionMode) { - case "", "default": + case "": return "" // caller's default + case string(session.ModeDefault): + return session.ModeDefault case string(session.ModePlan): return session.ModePlan case string(session.ModeAccept): @@ -455,7 +459,7 @@ func resolvePermissionMode(d port.Diagnostics, def agents.AgentDef) session.Perm default: d.Log(context.Background(), port.LevelWarn, "agent def references an unknown permissionMode; using the default", "agent", def.Name, "mode", def.PermissionMode, "origin", string(def.Origin)) - return "" + return session.ModeDefault } } diff --git a/internal/app/agentdefs_test.go b/internal/app/agentdefs_test.go index e6b3ec2b48..03ad49544f 100644 --- a/internal/app/agentdefs_test.go +++ b/internal/app/agentdefs_test.go @@ -524,3 +524,24 @@ func kvArgsContain(args []any, key, val string) bool { } return false } + +// TestResolvePermissionModeKeepsExplicitDefault pins that only an omitted +// permissionMode inherits the team default (which follows an auto or yolo +// parent); an explicit or unrecognised value pins the member's mode. +func TestResolvePermissionModeKeepsExplicitDefault(t *testing.T) { + for _, tc := range []struct { + in string + want session.PermissionMode + }{ + {"", ""}, + {"default", session.ModeDefault}, + {" default ", session.ModeDefault}, + {"plan", session.ModePlan}, + {"acceptEdits", session.ModeAccept}, + {"bogus", session.ModeDefault}, + } { + if got := resolvePermissionMode(port.NopDiagnostics{}, agents.AgentDef{Name: "m", PermissionMode: tc.in}); got != tc.want { + t.Errorf("resolvePermissionMode(%q) = %q, want %q", tc.in, got, tc.want) + } + } +} From a8a6a4563b5e7a67d86d72fc0a501f8ff35f4c63 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:33:50 +0300 Subject: [PATCH 38/48] fix(permissions): select checker enforcement from the executing child's mode A delegated child shares its parent's reviewRoot, whose reviewer was compiled with rules already demoted to advisory for a yolo parent. A member definition could correctly keep a narrower mode under that parent, yet a rejecting verdict on its action stayed advisory and unsafe inbound content was released. Subagent and Parallel children shared the same gap. The host reviewer now compiles the operator's undemoted rules, and the engine applies the yolo demotion per executing session in reviewPolicy (and skips the child permission review for a yolo child). A yolo session stays advisory while a narrower child of it enforces, and trajectory and evidence stay shared. Coverage and startup narration keep the demoted specs. Co-Authored-By: Claude Opus 5.5 --- engine/CHANGELOG.md | 9 ++ engine/agent/actionreview.go | 6 +- engine/agent/child_mode_inherit_test.go | 55 ++++++++++++ engine/agent/dispatch.go | 2 +- engine/agent/inboundreview.go | 21 +++-- engine/agent/review.go | 8 +- internal/app/child_mode_guardrail_test.go | 103 ++++++++++++++++++++++ internal/app/guardrails.go | 25 ++++-- 8 files changed, 210 insertions(+), 19 deletions(-) create mode 100644 internal/app/child_mode_guardrail_test.go diff --git a/engine/CHANGELOG.md b/engine/CHANGELOG.md index 681c044fab..1055a2f32a 100644 --- a/engine/CHANGELOG.md +++ b/engine/CHANGELOG.md @@ -459,6 +459,15 @@ The covered surface is the eight core packages (`session`, `governance`, `learni parent: it runs in the narrower of its stored mode and the mode a fresh child would get. No signature changes. +- **Contextual review enforcement follows the executing session's mode** — + the engine now demotes a `ReviewPolicyProvider`'s enforcement to advisory + for an executing `ModeYolo` session, and never consults + `PermissionReviewPolicyProvider` for a yolo child. A reviewer shared with + delegated children should report the operator's configured enforcement: + a yolo parent stays advisory while its narrower child keeps an enforcing + checker. A reviewer that already demoted for yolo is unaffected. Changed + (breaking, pre-v1 minor); no signature changes. + - **Atomic one-shot retry eligibility (issue #2273)** — `port.ScheduleOneShotReArmer.ReArmOneShot` now requires store-side atomic validation of current disabled/settled-failure state, one-shot retry policy, diff --git a/engine/agent/actionreview.go b/engine/agent/actionreview.go index 1857d8905a..6c22d99a97 100644 --- a/engine/agent/actionreview.go +++ b/engine/agent/actionreview.go @@ -686,7 +686,7 @@ func (e *Engine) prepareActionAssessment(ctx context.Context, r *Run, sess *sess func (e *Engine) reviewChildPermissionAsk(ctx context.Context, r *Run, sess *session.Session, env tool.Environment, ask session.PendingAsk) *uint64 { if e.deps.Role == "" || r == nil || r.reviewRoot == nil || r.reviewRoot.reviewer == nil || ask.AskProvenance != governance.AskProvenanceBuiltinSubstitutionFloor || - ask.Tool != tool.ShellToolName || sess.Mode == session.ModePlan { + ask.Tool != tool.ShellToolName || sess.Mode == session.ModePlan || sess.Mode == session.ModeYolo { return nil } call := session.NewToolCall(ask.Call, ask.Tool, append(json.RawMessage(nil), ask.Args...)) @@ -817,7 +817,7 @@ func (e *Engine) resolveActionAssessment(ctx context.Context, r *Run, sess *sess decision = "unresolved" result.Assessment = ReviewUnresolved } - _, enforce := reviewPolicy(r.reviewRoot.reviewer, call.Name, ReviewJobAction, assessment.err != nil) + _, enforce := reviewPolicy(r.reviewRoot.reviewer, sess.Mode, call.Name, ReviewJobAction, assessment.err != nil) if assessment.err != nil { var terminal GuardrailReviewTerminalFailure if errors.As(assessment.err, &terminal) && terminal.GuardrailReviewTerminalFailure() { @@ -938,7 +938,7 @@ func (e *Engine) reviewActionWithTail(ctx context.Context, r *Run, sess *session if r.reviewRoot == nil || r.reviewRoot.reviewer == nil { return session.ToolResult{}, nil, false, true } - if applies, _ := reviewPolicy(r.reviewRoot.reviewer, call.Name, ReviewJobAction, false); !applies { + if applies, _ := reviewPolicy(r.reviewRoot.reviewer, sess.Mode, call.Name, ReviewJobAction, false); !applies { if !r.reviewRoot.admitPrincipalRevisions(nil, auth.permissionReviewRevision) { res := session.NewToolError(call.ID, "contextual guardrail review context changed before execution; retry the action for a fresh assessment") e.publishToolResult(r, session.Event{Type: session.EvToolResult, Turn: turnIdx, ToolResult: ptr(res)}) diff --git a/engine/agent/child_mode_inherit_test.go b/engine/agent/child_mode_inherit_test.go index 8128695b3a..f582682278 100644 --- a/engine/agent/child_mode_inherit_test.go +++ b/engine/agent/child_mode_inherit_test.go @@ -254,3 +254,58 @@ func TestResumedChildMode(t *testing.T) { } } } + +// rejectingActionReviewer prohibits every action and enforces its finding. +type rejectingActionReviewer struct{} + +func (rejectingActionReviewer) Review(context.Context, agent.ToolReviewRequest, agent.ReviewEvidenceSource) (agent.ToolReviewResult, session.AuxiliaryUsage, error) { + return agent.ToolReviewResult{Assessment: agent.ReviewProhibited}, session.AuxiliaryUsage{}, nil +} + +func (rejectingActionReviewer) GuardrailReviewPolicy(_ string, job agent.ReviewJob, _ bool) (bool, bool) { + return job == agent.ReviewJobAction, true +} + +// TestSharedReviewerEnforcesForNarrowerChildOfYoloParent proves the reviewer a +// yolo parent shares with its Subagent child selects enforcement from the +// CHILD's mode: an explicitly default child's prohibited action is blocked, +// while an inheriting yolo child (like its parent) treats it as advisory. +func TestSharedReviewerEnforcesForNarrowerChildOfYoloParent(t *testing.T) { + for _, tc := range []struct { + name string + opts []agent.SubagentOption + want bool + }{ + {"explicit-default", []agent.SubagentOption{agent.WithChildMode(session.ModeDefault)}, false}, + {"inherit", nil, true}, + } { + t.Run(tc.name, func(t *testing.T) { + var executed atomic.Bool + probe := &fakeTool{name: "Probe", readOnly: true, + exec: func(_ context.Context, in session.ToolCall, _ tool.Workspace) (session.ToolResult, error) { + executed.Store(true) + return session.NewToolResult(in.ID, "probed"), nil + }} + childEngine := agent.NewEngine(agent.Deps{ + LLM: mockllm.New(mockllm.ToolCallTurn(toolCall("k1", "Probe", `{}`)), mockllm.TextTurn("child done")), + Catalog: catalogWith(t, probe), + Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), + Model: "child-model", + }) + task := agent.NewSubagentTool(childEngine, tc.opts...) + sess := newSession(t, session.Limits{}) + if err := sess.SetMode(session.ModeYolo); err != nil { + t.Fatal(err) + } + e := newEngine(agent.Deps{ + LLM: mockllm.New(mockllm.ToolCallTurn(toolCall("p1", "Subagent", `{"prompt":"go"}`)), mockllm.TextTurn("ok")), + Catalog: catalogWith(t, task), + ToolReviewer: rejectingActionReviewer{}, + }) + drainObserving(t, e.Run(context.Background(), sess, agent.MemEnv("/ws"), agent.RunRequest{Text: "go"}), nil) + if executed.Load() != tc.want { + t.Errorf("child Probe executed=%t under a yolo parent with a rejecting reviewer, want %t", executed.Load(), tc.want) + } + }) + } +} diff --git a/engine/agent/dispatch.go b/engine/agent/dispatch.go index 0a37f239ec..0dc27f5ea8 100644 --- a/engine/agent/dispatch.go +++ b/engine/agent/dispatch.go @@ -432,7 +432,7 @@ func (e *Engine) fanOutReadBatchActionAssessments(ctx context.Context, r *Run, s if r.reviewRoot == nil || r.reviewRoot.reviewer == nil { continue } - if applies, _ := reviewPolicy(r.reviewRoot.reviewer, p.call.Name, ReviewJobAction, false); applies { + if applies, _ := reviewPolicy(r.reviewRoot.reviewer, sess.Mode, p.call.Name, ReviewJobAction, false); applies { assessment := e.prepareActionAssessment(ctx, r, sess, env, p.call) p.assessment = &assessment reviewWG.Add(1) diff --git a/engine/agent/inboundreview.go b/engine/agent/inboundreview.go index 1351fd1776..365966f221 100644 --- a/engine/agent/inboundreview.go +++ b/engine/agent/inboundreview.go @@ -42,25 +42,32 @@ type inboundAssessment struct { err error applies bool enforce bool + mode session.PermissionMode principalRevision uint64 } -func reviewPolicy(reviewer ToolReviewer, toolName string, job ReviewJob, operationalFailure bool) (bool, bool) { +// reviewPolicy resolves the reviewer's configured applicability and enforcement +// for the EXECUTING session's mode. A shared reviewRoot carries the operator's +// undemoted rules, so a yolo session (no enforcing checker; advisory monitoring +// only) demotes enforcement here while a narrower delegated child of that yolo +// parent keeps it. +func reviewPolicy(reviewer ToolReviewer, mode session.PermissionMode, toolName string, job ReviewJob, operationalFailure bool) (bool, bool) { + applies, enforce := job == ReviewJobAction, true if policy, ok := reviewer.(ReviewPolicyProvider); ok { - return policy.GuardrailReviewPolicy(toolName, job, operationalFailure) + applies, enforce = policy.GuardrailReviewPolicy(toolName, job, operationalFailure) } // ToolReviewer predated inbound escrow. Reviewers that do not explicitly // advertise policy retain action-only behavior rather than unexpectedly // inspecting and holding every tool result. - return job == ReviewJobAction, true + return applies, enforce && mode != session.ModeYolo } func (e *Engine) prepareInboundAssessment(ctx context.Context, r *Run, sess *session.Session, env tool.Environment, call session.ToolCall, result session.ToolResult) inboundAssessment { if r.reviewRoot == nil || r.reviewRoot.reviewer == nil { return inboundAssessment{} } - applies, enforce := reviewPolicy(r.reviewRoot.reviewer, call.Name, ReviewJobInbound, false) - assessment := inboundAssessment{applies: applies, enforce: enforce} + applies, enforce := reviewPolicy(r.reviewRoot.reviewer, sess.Mode, call.Name, ReviewJobInbound, false) + assessment := inboundAssessment{applies: applies, enforce: enforce, mode: sess.Mode} if !applies { return assessment } @@ -115,7 +122,7 @@ func assessInbound(parent context.Context, r *Run, assessment *inboundAssessment if assessment.err != nil { assessment.result.Assessment = ReviewUnresolved recordReviewFailure(r.reviewRoot.reviewer, assessment.result, assessment.err) - _, assessment.enforce = reviewPolicy(r.reviewRoot.reviewer, assessment.request.EffectiveCall.Name, ReviewJobInbound, true) + _, assessment.enforce = reviewPolicy(r.reviewRoot.reviewer, assessment.mode, assessment.request.EffectiveCall.Name, ReviewJobInbound, true) var terminal GuardrailReviewTerminalFailure if errors.As(assessment.err, &terminal) && terminal.GuardrailReviewTerminalFailure() { assessment.enforce = true @@ -136,7 +143,7 @@ func assessInbound(parent context.Context, r *Run, assessment *inboundAssessment assessment.err = reviewFailure(ReviewFailureInvalidAssessment) } if assessment.err != nil { - _, assessment.enforce = reviewPolicy(r.reviewRoot.reviewer, assessment.request.EffectiveCall.Name, ReviewJobInbound, true) + _, assessment.enforce = reviewPolicy(r.reviewRoot.reviewer, assessment.mode, assessment.request.EffectiveCall.Name, ReviewJobInbound, true) var terminal GuardrailReviewTerminalFailure if errors.As(assessment.err, &terminal) && terminal.GuardrailReviewTerminalFailure() { assessment.enforce = true diff --git a/engine/agent/review.go b/engine/agent/review.go index f77b547275..5c37057719 100644 --- a/engine/agent/review.go +++ b/engine/agent/review.go @@ -157,14 +157,18 @@ type ReviewEvidencePreparer interface { // toolName and job identify the candidate rule; operationalFailure selects its // checker-down posture. The returns report whether review applies and whether a // finding or unresolved assessment is enforced. A ToolReviewer without this -// capability retains action-only enforcement. +// capability retains action-only enforcement. Report the operator's configured +// enforcement independent of permission mode: the engine demotes it to advisory +// for each executing yolo-mode session, including delegated children that share +// the reviewer. type ReviewPolicyProvider interface { GuardrailReviewPolicy(toolName string, job ReviewJob, operationalFailure bool) (applies, enforce bool) } // PermissionReviewPolicyProvider reports whether an exact child Shell call has // enabled, enforcing, matching action-review coverage. Advisory, skipped, and -// unmatched rules must return false. +// unmatched rules must return false. The engine never consults it for a +// yolo-mode child. type PermissionReviewPolicyProvider interface { GuardrailPermissionReviewEligible(session.ToolCall) bool } diff --git a/internal/app/child_mode_guardrail_test.go b/internal/app/child_mode_guardrail_test.go new file mode 100644 index 0000000000..29ac270a76 --- /dev/null +++ b/internal/app/child_mode_guardrail_test.go @@ -0,0 +1,103 @@ +package app + +import ( + "encoding/json" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/session" +) + +// TestYoloParentNarrowerTeamMemberKeepsEnforcingChecker drives the real +// composition: a yolo session forms a Team whose member definition pins +// permissionMode: default, and the checker rejects the member's Read. The +// shared reviewer must enforce for the narrower member (action blocked, unsafe +// inbound content withheld) while an inheriting member stays advisory, like +// its yolo parent. +func TestYoloParentNarrowerTeamMemberKeepsEnforcingChecker(t *testing.T) { + const canary = "MEMBER-READ-CANARY" + const prohibited = `{"assessment":"prohibited","concerns":["unsafe"],"evidence":[],"missing_evidence":[]}` + for _, tc := range []struct { + name, phase, agent string + wantLeak bool + }{ + {"action-narrow", "pre", "narrow", false}, + {"action-inherit", "pre", "", true}, + {"inbound-narrow", "post", "narrow", false}, + {"inbound-inherit", "post", "", true}, + } { + t.Run(tc.name, func(t *testing.T) { + workspace := t.TempDir() + if err := os.WriteFile(filepath.Join(workspace, "readme.txt"), []byte(canary+"\n"), 0o644); err != nil { + t.Fatal(err) + } + agentsDir := t.TempDir() + def := "---\nname: narrow\ndescription: narrow reader\npermissionMode: default\n---\nRead files when asked." + if err := os.WriteFile(filepath.Join(agentsDir, "narrow.md"), []byte(def), 0o644); err != nil { + t.Fatal(err) + } + member := `{"name":"lead","role":"read readme.txt"}` + if tc.agent != "" { + member = `{"name":"lead","role":"read readme.txt","agent":"` + tc.agent + `"}` + } + // One provider serves parent, member, and checker in call order. + provider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("team", "Team", json.RawMessage(`{"goal":"inspect","members":[`+member+`]}`))), + mockllm.ToolCallTurn(session.NewToolCall("member-read", "Read", json.RawMessage(`{"path":"readme.txt"}`))), + mockllm.TextTurn(prohibited), + mockllm.TextTurn("member done"), + mockllm.TextTurn("team report"), + mockllm.TextTurn("parent done"), + ) + built, err := buildIsolated(t, t.Context(), Config{ + Workspace: workspace, NoSoul: true, UseMock: true, MockProvider: provider, + Model: "main-model", GuardrailsModel: "guardrail-model", EnableTeams: true, + AgentsDirs: []string{agentsDir}, PermissionMode: "yolo", PermissionModeFlagSet: true, + GuardrailsRules: []GuardrailRule{{Match: "Read", Phases: []string{tc.phase}, Mode: "block"}}, + }) + if err != nil { + t.Fatal(err) + } + defer built.Close() + parent, err := built.Service.CreateSession(t.Context(), session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatal(err) + } + run, err := built.Service.StartRun(t.Context(), parent.ID, "inspect") + if err != nil { + t.Fatal(err) + } + var events []session.Event + for ev := range run.Events() { + events = append(events, ev) + } + built.Service.FinishRun(parent.ID, run) + memberSess, err := built.Service.GetSession(t.Context(), teamMemberSessionID(t, events)) + if err != nil { + t.Fatal(err) + } + wantMode := session.ModeYolo + if tc.agent != "" { + wantMode = session.ModeDefault + } + if memberSess.Mode != wantMode { + t.Fatalf("member mode = %q, want %q", memberSess.Mode, wantMode) + } + var read *session.ToolResult + for _, m := range memberSess.Conversation.Messages { + if m.ToolResult != nil && m.ToolResult.CallID == "member-read" { + read = m.ToolResult + } + } + if read == nil { + t.Fatalf("member Read produced no recorded result: %+v", memberSess.Conversation.Messages) + } + if leaked := strings.Contains(read.Content, canary); leaked != tc.wantLeak { + t.Fatalf("member Read result leaked=%t, want %t (enforcement must follow the member's own mode): %q", leaked, tc.wantLeak, read.Content) + } + }) + } +} diff --git a/internal/app/guardrails.go b/internal/app/guardrails.go index 3c7ac85ddd..57143114b8 100644 --- a/internal/app/guardrails.go +++ b/internal/app/guardrails.go @@ -326,7 +326,7 @@ func buildGuardrailsActionReviewer(cfg Config, provReg *providerRegistry, provid if base == nil { return nil } - specs, _ := effectiveGuardrailSpecs(cfg) + specs, _ := configuredGuardrailSpecs(cfg) rules, ok := compileGuardrailRules(cfg, specs) if !ok { return nil @@ -443,17 +443,31 @@ var defaultGuardrailSpecs = []modelhook.RuleSpec{ // ENFORCING: under auto the approve-once ask IS the auto-mode behaviour (the checker // blocks, an interactive human allows once — CC auto-mode parity), so demoting auto // would remove that very behaviour. The interactive approve-once path is gated on -// Deps.Interactive, NOT on posture. This is composition-only (no engine change) and -// posture is operator-tier, consistent with guardrails being operator-tier (no -// project-tier downgrade). +// Deps.Interactive, NOT on posture. Posture is operator-tier, consistent with +// guardrails being operator-tier (no project-tier downgrade). These demoted specs +// feed coverage and narration; the engine reviewer compiles configuredGuardrailSpecs +// and the engine applies the same yolo demotion per executing session. func effectiveGuardrailSpecs(cfg Config) (specs []modelhook.RuleSpec, usedDefaults bool) { + specs, usedDefaults = configuredGuardrailSpecs(cfg) + for i := range specs { + specs[i].Mode = demoteForPosture(cfg, specs[i].Mode) + } + return specs, usedDefaults +} + +// configuredGuardrailSpecs returns the operator's rule specs (or the default set) +// WITHOUT the yolo demotion. The engine reviewer compiles these: a reviewRoot is +// shared with delegated children, so the engine selects enforcement from each +// executing session's mode (a yolo session is advisory, a narrower child of it +// still enforces) instead of freezing the parent's demotion into the rules. +func configuredGuardrailSpecs(cfg Config) (specs []modelhook.RuleSpec, usedDefaults bool) { if len(cfg.GuardrailsRules) > 0 { out := make([]modelhook.RuleSpec, 0, len(cfg.GuardrailsRules)) for i, gr := range cfg.GuardrailsRules { out = append(out, modelhook.RuleSpec{ Match: gr.Match, Phases: gr.Phases, - Mode: demoteForPosture(cfg, gr.Mode), + Mode: gr.Mode, Prompt: gr.Prompt, FailClosed: gr.FailClosed, FailClosedSet: gr.FailClosedSet, @@ -472,7 +486,6 @@ func effectiveGuardrailSpecs(cfg Config) (specs []modelhook.RuleSpec, usedDefaul if dm := strings.TrimSpace(cfg.GuardrailsDefaultMode); dm != "" { s.Mode = dm } - s.Mode = demoteForPosture(cfg, s.Mode) out[i] = s } return out, true From 7f070b4867e9729c5106800dd5bd02818baf27da Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:38:29 +0300 Subject: [PATCH 39/48] feat(permissions): recover a refused-mode awaiting session with a SetMode downgrade A stored session parked awaiting an approval in a mode the server no longer admits had no recovery short of re-enabling that mode: every resume is refused by the stored-mode check, durable cancel reports no active run, and the aggregate refuses SetMode mid-turn. SetMode to an admitted, strictly lower mode now cancels the pending turn without any engine, provider, or tool work and applies the mode in one save, under runEntryMu and the mutation lease on the snapshot reloaded under that lease. The next run repairs history through the ordinary interrupt path. Every other awaiting SetMode keeps the InvalidArgument refusal, and the refusal for an awaiting session now names this downgrade as the recovery. API compatibility: additive. SetMode widens from InvalidArgument to success only for sessions that are unrecoverable today; no request or response shape changes and no existing success path changes. Advertised by the new refused_mode_recovery feature identifier, mirrored in the TypeScript SDK. Co-Authored-By: Claude Opus 5.5 --- contracts/gen/go/mecatl/v1/harness_grpc.pb.go | 8 + contracts/proto/mecatl/v1/harness.proto | 4 + docs/architecture/api-surface.md | 5 +- docs/architecture/governance.md | 4 +- internal/adapter/server/features.go | 8 + internal/adapter/server/mode_recovery_test.go | 181 ++++++++++++++++++ internal/adapter/server/service.go | 33 +++- sdk/typescript/etc/mecatl-sdk-deno.api.md | 1 + sdk/typescript/etc/mecatl-sdk-node.api.md | 1 + sdk/typescript/etc/mecatl-sdk.api.md | 1 + .../src/gen/mecatl/v1/harness_pb.ts | 4 + sdk/typescript/src/server.ts | 1 + sdk/typescript/test/server-discovery.test.ts | 2 + .../permissions-and-posture.md | 10 +- user-docs/reference/grpc-schema.md | 2 +- .../reference/typescript-sdk-api/core.md | 1 + 16 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 internal/adapter/server/mode_recovery_test.go diff --git a/contracts/gen/go/mecatl/v1/harness_grpc.pb.go b/contracts/gen/go/mecatl/v1/harness_grpc.pb.go index 39137ce521..bf91c54326 100644 --- a/contracts/gen/go/mecatl/v1/harness_grpc.pb.go +++ b/contracts/gen/go/mecatl/v1/harness_grpc.pb.go @@ -169,6 +169,10 @@ type HarnessServiceClient interface { // SetMode changes an existing session's permission posture. The session aggregate // remains authoritative: a mid-turn change is rejected with InvalidArgument, so // clients that want "next prompt" semantics must defer and retry once idle. + // One exception, advertised by the refused_mode_recovery feature: for a stored + // session awaiting an approval in a mode the server no longer admits, a change + // to an admitted, strictly lower mode cancels the pending turn without running + // it and applies the mode. SetMode(ctx context.Context, in *SetModeRequest, opts ...grpc.CallOption) (*SetModeResponse, error) // CloseSession ends a session and releases its server-side resources (learned // permission rules, bound placement, and any per-session engine). Idempotent: @@ -1447,6 +1451,10 @@ type HarnessServiceServer interface { // SetMode changes an existing session's permission posture. The session aggregate // remains authoritative: a mid-turn change is rejected with InvalidArgument, so // clients that want "next prompt" semantics must defer and retry once idle. + // One exception, advertised by the refused_mode_recovery feature: for a stored + // session awaiting an approval in a mode the server no longer admits, a change + // to an admitted, strictly lower mode cancels the pending turn without running + // it and applies the mode. SetMode(context.Context, *SetModeRequest) (*SetModeResponse, error) // CloseSession ends a session and releases its server-side resources (learned // permission rules, bound placement, and any per-session engine). Idempotent: diff --git a/contracts/proto/mecatl/v1/harness.proto b/contracts/proto/mecatl/v1/harness.proto index 8f654cfe53..95ba60614c 100644 --- a/contracts/proto/mecatl/v1/harness.proto +++ b/contracts/proto/mecatl/v1/harness.proto @@ -76,6 +76,10 @@ service HarnessService { // SetMode changes an existing session's permission posture. The session aggregate // remains authoritative: a mid-turn change is rejected with InvalidArgument, so // clients that want "next prompt" semantics must defer and retry once idle. + // One exception, advertised by the refused_mode_recovery feature: for a stored + // session awaiting an approval in a mode the server no longer admits, a change + // to an admitted, strictly lower mode cancels the pending turn without running + // it and applies the mode. rpc SetMode(SetModeRequest) returns (SetModeResponse); // CloseSession ends a session and releases its server-side resources (learned diff --git a/docs/architecture/api-surface.md b/docs/architecture/api-surface.md index ba040646d7..4e32ce6f2a 100644 --- a/docs/architecture/api-surface.md +++ b/docs/architecture/api-surface.md @@ -163,7 +163,10 @@ the source untouched, with one exception: clearing a running source cancels it f a later failure publishes no successor but the source stays cancelled. `SetMode` is rejected mid-turn, because changing posture would race permission checks -already in flight; clients defer it to the next prompt. `CompactSession` likewise runs +already in flight; clients defer it to the next prompt. The exception is a stored session +awaiting an approval in a mode the server no longer admits: a switch to an admitted, lower +mode cancels the pending turn without running it, then applies the mode +(`refused_mode_recovery`). `CompactSession` likewise runs only at an idle or terminal boundary. ## Scheduled tasks diff --git a/docs/architecture/governance.md b/docs/architecture/governance.md index db72ef6951..1268003dbd 100644 --- a/docs/architecture/governance.md +++ b/docs/architecture/governance.md @@ -79,7 +79,9 @@ whose default mode is `auto` refuses to start without one. Unchecked autonomy is explicit `yolo` choice, where a configured checker is advisory. `admitStoredMode` re-checks a persisted session's mode at run, approval resume, fork, and clear, so a mode admitted under a looser deployment fails with `FailedPrecondition` until the owner -switches it; history is untouched. A project file's `permissionMode:` is ignored with a +switches it; history is untouched. A session parked awaiting an approval in such a mode +recovers through `SetMode` to an admitted, lower mode, which cancels the pending turn +without running it (`cancelRefusedAwaiting`). A project file's `permissionMode:` is ignored with a warning, and `auto` or `yolo` are refused as root without a declared sandbox. Delegated children receive the parent session's mode through `parentCaps.parentMode`: diff --git a/internal/adapter/server/features.go b/internal/adapter/server/features.go index 7315b162bc..d08cafac38 100644 --- a/internal/adapter/server/features.go +++ b/internal/adapter/server/features.go @@ -94,6 +94,13 @@ const ( // capability cannot answer this: an older server advertises auto/yolo // posture without supporting these session modes. FeatureSessionPermissionModes = "session_permission_modes" + + // FeatureRefusedModeRecovery reports that SetMode recovers a stored session + // parked awaiting an approval in a mode this server no longer admits: a + // SetMode to an admitted, strictly lower mode cancels the pending turn + // without running it and applies the mode, instead of refusing mid-turn. + // Every other SetMode on an awaiting session is still refused. + FeatureRefusedModeRecovery = "refused_mode_recovery" ) // FeatureScope is what the DEPLOYMENT permits, as distinct from what the build @@ -131,6 +138,7 @@ var allFeatures = []string{ FeatureHTTPSteer, FeatureMCPServersOnCreate, FeaturePromptFreeControls, + FeatureRefusedModeRecovery, FeatureServerInfo, FeatureSessionActivityInventory, FeatureSessionAgentDefinitions, diff --git a/internal/adapter/server/mode_recovery_test.go b/internal/adapter/server/mode_recovery_test.go new file mode 100644 index 0000000000..3b785a1824 --- /dev/null +++ b/internal/adapter/server/mode_recovery_test.go @@ -0,0 +1,181 @@ +package server_test + +import ( + "context" + "encoding/json" + "errors" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/stacklok/mecatl/engine/adapter/memlease" + "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/adapter/permstore" + "github.com/stacklok/mecatl/engine/adapter/wallclock" + "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/server" +) + +// parkAwaitingInMode drives a default session to a durable pending Write ask +// on a loose deployment, then rewrites the stored mode to model a snapshot +// parked under a deployment that admitted stored. +func parkAwaitingInMode(t *testing.T, store port.SessionStore, stored session.PermissionMode) (session.SessionID, string) { + t.Helper() + ctx := context.Background() + var ran atomic.Int64 + loose := newAskingService(t, store, permstore.New(), &ran, + mockllm.New(mockllm.ToolCallTurn(session.NewToolCall("w1", "Write", json.RawMessage(`{"path":"a.go"}`)))), false) + sess, err := loose.CreateSession(ctx, session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + askID := driveServiceToAwaiting(t, loose, sess.ID) + parked, err := store.Load(ctx, sess.ID) + if err != nil { + t.Fatal(err) + } + parked.Mode = stored + if err := store.Save(ctx, parked); err != nil { + t.Fatal(err) + } + return sess.ID, askID +} + +// recoveryService is a restarted deployment over store with the given ceiling +// and checker; lease, when non-nil, is shared with a peer. +func recoveryService(t *testing.T, store port.SessionStore, llm *mockllm.Provider, ran *atomic.Int64, ceiling session.PermissionMode, checker bool, lease port.SessionLease) *server.Service { + t.Helper() + cat := tool.NewCatalog() + cat.MustRegister(&writeAskTool{ran: ran}) + cfg := server.Config{ + Engine: agent.NewEngine(agent.Deps{LLM: llm, Catalog: cat, Policy: permpolicy.NewPolicy(nil, permstore.New()), Model: "test-model", Store: store}), + Store: store, + Now: func() time.Time { return time.Unix(0, 0) }, + MaxAllowedMode: ceiling, + EnforcingCheckerConfigured: checker, + } + if lease != nil { + cfg.SessionLease, cfg.LeaseOwner, cfg.LeaseTTL, cfg.LeaseRenewInterval = lease, "recovering", time.Minute, time.Hour + } + svc, err := newPlacementTestService(cfg) + if err != nil { + t.Fatalf("new service: %v", err) + } + t.Cleanup(svc.Close) + return svc +} + +// TestSetModeDowngradeRecoversRefusedAwaitingSession pins option B's recovery: +// a stored session awaiting an approval in a mode the restarted server refuses +// is unrecoverable by approval, and a SetMode to an admitted lower mode cancels +// the pending turn without any provider or tool work and applies the mode in +// one save; the next StartRun then runs in the new mode. +func TestSetModeDowngradeRecoversRefusedAwaitingSession(t *testing.T) { + ctx := context.Background() + store := memstore.New() + id, askID := parkAwaitingInMode(t, store, session.ModeYolo) + + var ran atomic.Int64 + llm := mockllm.New(mockllm.TextTurn("continued")) + svc := recoveryService(t, store, llm, &ran, session.ModeAccept, true, nil) + + _, err := svc.ApproveRun(ctx, id, askID, session.VerdictAllowOnce, "") + if !errors.Is(err, server.ErrFailedPrecondition) || !strings.Contains(err.Error(), "SetMode to an admitted lower mode") { + t.Fatalf("ApproveRun err = %v, want FailedPrecondition naming the SetMode downgrade", err) + } + + got, err := svc.SetMode(ctx, id, session.ModeDefault) + if err != nil { + t.Fatalf("SetMode(default) on refused awaiting session: %v", err) + } + if got.Mode != session.ModeDefault || got.State != session.StateCancelled { + t.Fatalf("SetMode returned mode %q state %q, want default/cancelled", got.Mode, got.State) + } + if llm.Calls() != 0 || ran.Load() != 0 { + t.Fatalf("recovery ran work: provider calls %d, tool executions %d", llm.Calls(), ran.Load()) + } + kept, err := store.Load(ctx, id) + if err != nil { + t.Fatal(err) + } + if _, pending := kept.PendingAsk(); pending || kept.Mode != session.ModeDefault || kept.State != session.StateCancelled { + t.Fatalf("stored after recovery: mode %q state %q pending %t", kept.Mode, kept.State, pending) + } + if _, err := svc.ApproveRun(ctx, id, askID, session.VerdictAllowOnce, ""); err == nil { + t.Fatal("the cancelled ask still resumed") + } + + run, err := svc.StartRun(ctx, id, "continue") + if err != nil { + t.Fatalf("StartRun after recovery: %v", err) + } + drainRun(t, run) + svc.FinishRun(id, run) + if llm.Calls() != 1 || ran.Load() != 0 { + t.Fatalf("next run: provider calls %d, tool executions %d; want 1, 0", llm.Calls(), ran.Load()) + } + after, err := store.Load(ctx, id) + if err != nil { + t.Fatal(err) + } + if after.Mode != session.ModeDefault || after.State != session.StateCompleted { + t.Fatalf("after next run: mode %q state %q, want default/completed", after.Mode, after.State) + } +} + +// TestSetModeOnAwaitingSessionStillRefusedOutsideRecovery pins that only the +// narrow recovery widens SetMode: every other awaiting SetMode is refused with +// the pending ask intact and no work run. +func TestSetModeOnAwaitingSessionStillRefusedOutsideRecovery(t *testing.T) { + ctx := context.Background() + for _, tc := range []struct { + name string + stored session.PermissionMode + ceiling session.PermissionMode + checker bool + target session.PermissionMode + peer bool + want error + }{ + {"stored mode still admitted", session.ModeAccept, session.ModeAccept, true, session.ModeDefault, false, server.ErrInvalidArgument}, + {"target above ceiling", session.ModeYolo, session.ModeAccept, true, session.ModeAuto, false, server.ErrInvalidArgument}, + {"target not lower", session.ModeAuto, session.ModeYolo, false, session.ModeYolo, false, server.ErrInvalidArgument}, + {"peer holds the lease", session.ModeYolo, session.ModeAccept, true, session.ModeDefault, true, server.ErrSessionLeasedElsewhere}, + } { + t.Run(tc.name, func(t *testing.T) { + store := memstore.New() + id, askID := parkAwaitingInMode(t, store, tc.stored) + var lease port.SessionLease + if tc.peer { + shared := memlease.New(wallclock.Clock{}, time.Minute) + if _, err := shared.Acquire(ctx, id, "peer"); err != nil { + t.Fatalf("peer Acquire: %v", err) + } + lease = shared + } + var ran atomic.Int64 + llm := mockllm.New(mockllm.TextTurn("must not run")) + svc := recoveryService(t, store, llm, &ran, tc.ceiling, tc.checker, lease) + + if _, err := svc.SetMode(ctx, id, tc.target); !errors.Is(err, tc.want) { + t.Fatalf("SetMode(%s) err = %v, want %v", tc.target, err, tc.want) + } + if llm.Calls() != 0 || ran.Load() != 0 { + t.Fatalf("refusal ran work: provider calls %d, tool executions %d", llm.Calls(), ran.Load()) + } + kept, err := store.Load(ctx, id) + if err != nil { + t.Fatal(err) + } + if pending, ok := kept.PendingAsk(); kept.State != session.StateAwaiting || !ok || pending.AskID != askID || kept.Mode != tc.stored { + t.Fatalf("refusal changed the session: state %q mode %q pending %t", kept.State, kept.Mode, ok) + } + }) + } +} diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index d228ef263c..9db1e23769 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -4759,7 +4759,9 @@ func (s *Service) managementTargetAwaitingDrain(ctx context.Context, id session. // mode, and propagates session.ErrIllegalTransition (wrapped as ErrInvalidArgument) // when the session is mid-turn (running/awaiting) — the aggregate refuses a mode // change while a turn is in flight, so the caller must defer it to the next -// prompt. A change to the mode the session already has is a no-op success. +// prompt. The one exception is cancelRefusedAwaiting's recovery for a stored +// awaiting session whose mode this server refuses. A change to the mode the +// session already has is a no-op success. func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode session.PermissionMode) (*session.Session, error) { if s.draining.Load() { return nil, fmt.Errorf("%w: %q", ErrUnavailable, id) @@ -4805,6 +4807,9 @@ func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode sessio return nil, loadErr } sess = loaded + if err := s.cancelRefusedAwaiting(sess, mode); err != nil { + return nil, err + } } if sess.AgentDefinitionName != "" { @@ -4882,14 +4887,38 @@ func (s *Service) AdmittedModes() []session.PermissionMode { // admitStoredMode re-admits a persisted session's mode against the CURRENT // ceiling and checker before execution, approval resume, or successor // publication. A refusal leaves the session and its history untouched; the -// owner can SetMode to an admitted mode and continue. +// owner can SetMode to an admitted mode and continue. For a session awaiting +// an approval that SetMode must be a downgrade, which cancels the pending turn +// (cancelRefusedAwaiting). func (s *Service) admitStoredMode(sess *session.Session) error { if err := s.admitMode(sess.Mode); err != nil { + if sess.State == session.StateAwaiting { + return fmt.Errorf("%w: session %q is in permission mode %q, which this server does not admit (%v), and its pending approval cannot resume in that mode; SetMode to an admitted lower mode cancels the pending turn without running it and lets the session continue", ErrFailedPrecondition, sess.ID, sess.Mode, err) + } return fmt.Errorf("%w: session %q is in permission mode %q, which this server does not admit (%v); switch it to an admitted mode with SetMode to continue", ErrFailedPrecondition, sess.ID, sess.Mode, err) } return nil } +// cancelRefusedAwaiting is the recovery for a stored session parked awaiting +// an approval in a mode this server refuses: admitStoredMode blocks every +// resume, and the aggregate refuses SetMode mid-turn. When the requested mode +// is admitted (the caller checked) and strictly lower than the stored mode, it +// cancels the pending turn without executing anything, so the caller's mode +// change and single save are legal; the next run repairs the history through +// the ordinary interrupt path. Every other awaiting session is left for the +// aggregate's mid-turn refusal. The caller holds runEntryMu and the mutation +// lease, found no live run, and passes the snapshot loaded under that lease. +func (s *Service) cancelRefusedAwaiting(sess *session.Session, mode session.PermissionMode) error { + if sess.State != session.StateAwaiting || s.admitMode(sess.Mode) == nil || modeRank(mode) >= modeRank(sess.Mode) { + return nil + } + if err := sess.Cancel(); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidArgument, err) + } + return nil +} + // admitLeasedMode re-admits the AUTHORITATIVE stored mode once this process // holds id's session lease. beginRunAdmission checked the pre-lease snapshot // only: while this request waited for the lease, a peer on a looser diff --git a/sdk/typescript/etc/mecatl-sdk-deno.api.md b/sdk/typescript/etc/mecatl-sdk-deno.api.md index e5f055749f..e009d6566e 100644 --- a/sdk/typescript/etc/mecatl-sdk-deno.api.md +++ b/sdk/typescript/etc/mecatl-sdk-deno.api.md @@ -1376,6 +1376,7 @@ export const ServerFeature: { readonly HttpSteer: "http_steer"; readonly McpServersOnCreate: "mcp_servers_on_create"; readonly PromptFreeControls: "prompt_free_controls"; + readonly RefusedModeRecovery: "refused_mode_recovery"; readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; diff --git a/sdk/typescript/etc/mecatl-sdk-node.api.md b/sdk/typescript/etc/mecatl-sdk-node.api.md index 416378d41d..8935c4ea8a 100644 --- a/sdk/typescript/etc/mecatl-sdk-node.api.md +++ b/sdk/typescript/etc/mecatl-sdk-node.api.md @@ -1405,6 +1405,7 @@ export const ServerFeature: { readonly HttpSteer: "http_steer"; readonly McpServersOnCreate: "mcp_servers_on_create"; readonly PromptFreeControls: "prompt_free_controls"; + readonly RefusedModeRecovery: "refused_mode_recovery"; readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; diff --git a/sdk/typescript/etc/mecatl-sdk.api.md b/sdk/typescript/etc/mecatl-sdk.api.md index e8073cad74..5647b47e57 100644 --- a/sdk/typescript/etc/mecatl-sdk.api.md +++ b/sdk/typescript/etc/mecatl-sdk.api.md @@ -1328,6 +1328,7 @@ export const ServerFeature: { readonly HttpSteer: "http_steer"; readonly McpServersOnCreate: "mcp_servers_on_create"; readonly PromptFreeControls: "prompt_free_controls"; + readonly RefusedModeRecovery: "refused_mode_recovery"; readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; diff --git a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts index b4c4af3a0e..2e88ec9ead 100644 --- a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts +++ b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts @@ -11145,6 +11145,10 @@ export const HarnessService: GenService<{ * SetMode changes an existing session's permission posture. The session aggregate * remains authoritative: a mid-turn change is rejected with InvalidArgument, so * clients that want "next prompt" semantics must defer and retry once idle. + * One exception, advertised by the refused_mode_recovery feature: for a stored + * session awaiting an approval in a mode the server no longer admits, a change + * to an admitted, strictly lower mode cancels the pending turn without running + * it and applies the mode. * * @generated from rpc mecatl.v1.HarnessService.SetMode */ diff --git a/sdk/typescript/src/server.ts b/sdk/typescript/src/server.ts index cdd250012a..50a701de38 100644 --- a/sdk/typescript/src/server.ts +++ b/sdk/typescript/src/server.ts @@ -23,6 +23,7 @@ export const ServerFeature = { HttpSteer: "http_steer", McpServersOnCreate: "mcp_servers_on_create", PromptFreeControls: "prompt_free_controls", + RefusedModeRecovery: "refused_mode_recovery", ServerInfo: "server_info", SessionActivityInventory: "session_activity_inventory", SessionAgentDefinitions: "session_agent_definitions", diff --git a/sdk/typescript/test/server-discovery.test.ts b/sdk/typescript/test/server-discovery.test.ts index 4d27a9d74c..7c8c2100f1 100644 --- a/sdk/typescript/test/server-discovery.test.ts +++ b/sdk/typescript/test/server-discovery.test.ts @@ -264,6 +264,7 @@ describe("SDK server discovery", () => { HttpSteer: "http_steer", McpServersOnCreate: "mcp_servers_on_create", PromptFreeControls: "prompt_free_controls", + RefusedModeRecovery: "refused_mode_recovery", ServerInfo: "server_info", SessionActivityInventory: "session_activity_inventory", SessionAgentDefinitions: "session_agent_definitions", @@ -992,6 +993,7 @@ describe("SDK server discovery", () => { 'readonly HttpSteer: "http_steer";', 'readonly McpServersOnCreate: "mcp_servers_on_create";', 'readonly PromptFreeControls: "prompt_free_controls";', + 'readonly RefusedModeRecovery: "refused_mode_recovery";', 'readonly ServerInfo: "server_info";', 'readonly SessionActivityInventory: "session_activity_inventory";', 'readonly SessionAgentDefinitions: "session_agent_definitions";', diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index ac29b41d8e..470df6bfb9 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -124,15 +124,19 @@ What happens when the cycle lands on a mode depends on the server ceiling: The server also refuses `auto` when it has no enforcing guardrails checker. The session keeps its current mode, and the footer gives the server's reason. -A session waiting on an approval cannot change mode. Answer the pending request -first: it resolves under the mode it was raised in, and the new mode applies +A session waiting on an approval cannot change mode, except to recover from a +refused mode as described below. Answer the pending request first: it resolves under the mode it was raised in, and the new mode applies from the next run. A mode change never stops a command that has already started. If the server restarts with a lower ceiling, or without the checker `auto` needs, a stored session in a mode it no longer admits refuses to run, resume an approval, fork, or clear until its owner switches it to an admitted mode. Its -history is unchanged. +history is unchanged. If that session is waiting on an approval, switch it to an +admitted mode lower than its stored one: the server cancels the pending request +without running it, then applies the mode, and your next prompt continues the +conversation. Servers that support this advertise the `refused_mode_recovery` +feature identifier. The restart a ceiling change needs depends on how you connect: diff --git a/user-docs/reference/grpc-schema.md b/user-docs/reference/grpc-schema.md index bee3ea25a5..f787a154f5 100644 --- a/user-docs/reference/grpc-schema.md +++ b/user-docs/reference/grpc-schema.md @@ -39,7 +39,7 @@ the bidi Converse stream that drives one agent run. | **RPC:** `ListGuardrailCoverage`
**Request:** `ListGuardrailCoverageRequest`
**Response:** `ListGuardrailCoverageResponse` | Client streamingNo | Server streamingNo | | | **RPC:** `GetGuardrailReviewDetail`
**Request:** `GetGuardrailReviewDetailRequest`
**Response:** `GetGuardrailReviewDetailResponse` | Client streamingNo | Server streamingNo | | | **RPC:** `GetSessionTranscript`
**Request:** `GetSessionTranscriptRequest`
**Response:** `GetSessionTranscriptResponse` | Client streamingNo | Server streamingNo | DescriptionGetSessionTranscript returns the authoritative, snapshot-derived human transcript for one owned session. It is read-only and does not use EventLog. | -| **RPC:** `SetMode`
**Request:** `SetModeRequest`
**Response:** `SetModeResponse` | Client streamingNo | Server streamingNo | DescriptionSetMode changes an existing session's permission posture. The session aggregate remains authoritative: a mid-turn change is rejected with InvalidArgument, so clients that want "next prompt" semantics must defer and retry once idle. | +| **RPC:** `SetMode`
**Request:** `SetModeRequest`
**Response:** `SetModeResponse` | Client streamingNo | Server streamingNo | DescriptionSetMode changes an existing session's permission posture. The session aggregate remains authoritative: a mid-turn change is rejected with InvalidArgument, so clients that want "next prompt" semantics must defer and retry once idle. One exception, advertised by the refused_mode_recovery feature: for a stored session awaiting an approval in a mode the server no longer admits, a change to an admitted, strictly lower mode cancels the pending turn without running it and applies the mode. | | **RPC:** `CloseSession`
**Request:** `CloseSessionRequest`
**Response:** `CloseSessionResponse` | Client streamingNo | Server streamingNo | DescriptionCloseSession ends a session and releases its server-side resources (learned permission rules, bound placement, and any per-session engine). Idempotent: closing an unknown or already-closed session via the wire returns NotFound only for a never-created id; an already-released session succeeds. | | **RPC:** `RenameSession`
**Request:** `RenameSessionRequest`
**Response:** `RenameSessionResponse` | Client streamingNo | Server streamingNo | DescriptionRenameSession explicitly replaces an idle main session's title. | | **RPC:** `DeleteSession`
**Request:** `DeleteSessionRequest`
**Response:** `DeleteSessionResponse` | Client streamingNo | Server streamingNo | DescriptionDeleteSession physically removes an idle main session and its sidecars. | diff --git a/user-docs/reference/typescript-sdk-api/core.md b/user-docs/reference/typescript-sdk-api/core.md index d3ed6ab7e7..9f4f9df94c 100644 --- a/user-docs/reference/typescript-sdk-api/core.md +++ b/user-docs/reference/typescript-sdk-api/core.md @@ -7499,6 +7499,7 @@ ServerFeature: { readonly HttpSteer: "http_steer"; readonly McpServersOnCreate: "mcp_servers_on_create"; readonly PromptFreeControls: "prompt_free_controls"; + readonly RefusedModeRecovery: "refused_mode_recovery"; readonly ServerInfo: "server_info"; readonly SessionActivityInventory: "session_activity_inventory"; readonly SessionAgentDefinitions: "session_agent_definitions"; From 2c73c70235e40c85eb93c893f44d6b1ddbfbee18 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:40:03 +0300 Subject: [PATCH 40/48] fix(permissions): refuse settings permissionMode with deprecated --posture or --yolo A settings.yaml permissionMode: token combined with the deprecated --yolo flag let resolvePosture raise the posture to yolo while the token's session mode and ceiling stayed put, and --posture silently out-ranked the token even though the key is documented to out-rank the deprecated surface. Either way the operator had to guess which permission source won. The cmd roots already refuse --permission-mode with these flags. Build now refuses the settings key combined with --posture or --yolo, naming both migrations: drop the flag to keep the key, or replace it with --permission-mode, which overrides the key. --trust-project is not deprecated and still combines with the key. Co-Authored-By: Claude Opus 5.5 --- cmd/mecated/permission_mode_test.go | 72 +++++++++++++++++++ cmd/mecatequi/permission_mode_test.go | 52 ++++++++++++++ cmd/mecatui/permission_mode_test.go | 66 +++++++++++++++++ internal/app/permission_mode.go | 56 +++++++++++---- .../permissions-and-posture.md | 5 +- 5 files changed, 235 insertions(+), 16 deletions(-) diff --git a/cmd/mecated/permission_mode_test.go b/cmd/mecated/permission_mode_test.go index b233778d83..7b2f3435f3 100644 --- a/cmd/mecated/permission_mode_test.go +++ b/cmd/mecated/permission_mode_test.go @@ -3,6 +3,8 @@ package main import ( "context" "log/slog" + "os" + "path/filepath" "strings" "testing" @@ -171,6 +173,76 @@ func TestCombinedLegacyAliasesBuildRaisedPair(t *testing.T) { } } +// TestSettingsPermissionModeRefusesDeprecatedFlags drives parseFlags, +// appConfig, and app.Build with an operator settings.yaml carrying +// permissionMode: plan. The deprecated --yolo and --posture flags cannot be +// combined with it, exactly as they cannot be combined with --permission-mode; +// the token alone, the deprecated flag alone, --permission-mode over the key, +// and the non-deprecated --trust-project still build. +func TestSettingsPermissionModeRefusesDeprecatedFlags(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + settings := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(settings, []byte("permissionMode: plan\n"), 0o600); err != nil { + t.Fatal(err) + } + build := func(t *testing.T, argv ...string) (*app.Built, error) { + t.Helper() + cfg, err := parseFlags(append([]string{"--workspace", t.TempDir(), "--guardrails", "off"}, argv...)) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + ac := appConfig(cfg, nil, nil, nil, nil, port.NopDiagnostics{}) + ac.UseMock, ac.NoSoul, ac.Privileged = true, true, false + return buildIsolated(t, context.Background(), ac) + } + for name, tc := range map[string]struct { + argv []string + want string + }{ + "yolo": {[]string{"--permission-config", settings, "--yolo"}, "--permission-mode yolo"}, + "posture": {[]string{"--permission-config", settings, "--posture", "auto"}, "--permission-mode auto"}, + "posture strict": {[]string{"--permission-config", settings, "--posture", "strict"}, "--permission-mode default"}, + } { + t.Run("refuses "+name, func(t *testing.T) { + built, err := build(t, tc.argv...) + if err == nil { + built.Close() + t.Fatalf("%q: settings permissionMode plus a deprecated flag must refuse to build", tc.argv) + } + for _, want := range []string{"permissionMode: plan", "cannot be combined", "keep permissionMode: plan", tc.want} { + if !strings.Contains(err.Error(), want) { + t.Errorf("%q: refusal must name %q; got %v", tc.argv, want, err) + } + } + }) + } + for name, tc := range map[string]struct { + argv []string + want session.PermissionMode + }{ + "settings token alone": {[]string{"--permission-config", settings}, session.ModePlan}, + "settings token with trust": {[]string{"--permission-config", settings, "--trust-project"}, session.ModePlan}, + "permission-mode over the key": {[]string{"--permission-config", settings, "--permission-mode", "yolo"}, session.ModeYolo}, + "yolo alone": {[]string{"--yolo"}, session.ModeYolo}, + "posture alone": {[]string{"--posture", "strict"}, session.ModeDefault}, + } { + t.Run("builds "+name, func(t *testing.T) { + built, err := build(t, tc.argv...) + if err != nil { + t.Fatalf("%q: app.Build: %v", tc.argv, err) + } + defer built.Close() + sess, err := built.Service.CreateSession(context.Background(), "", session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + if sess.Mode != tc.want { + t.Fatalf("%q: unspecified-mode session started in %q, want %q", tc.argv, sess.Mode, tc.want) + } + }) + } +} + func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { for _, tc := range []struct { name string diff --git a/cmd/mecatequi/permission_mode_test.go b/cmd/mecatequi/permission_mode_test.go index a919603bda..f75c5a69ac 100644 --- a/cmd/mecatequi/permission_mode_test.go +++ b/cmd/mecatequi/permission_mode_test.go @@ -387,3 +387,55 @@ func TestShippedAllowAllDefaultsDeclareCheckerChoice(t *testing.T) { } }) } + +// TestSettingsPermissionModeRefusesDeprecatedPosture drives parseFlags, +// appConfig, and app.Build with an operator settings.yaml carrying +// permissionMode: plan. The deprecated --posture cannot be combined with it; +// the token alone and --posture alone still build. +func TestSettingsPermissionModeRefusesDeprecatedPosture(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + settings := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(settings, []byte("permissionMode: plan\n"), 0o600); err != nil { + t.Fatal(err) + } + build := func(t *testing.T, args ...string) (*app.Built, error) { + t.Helper() + repo := t.TempDir() + initTestRepo(t, repo) + f, err := parseFlags(append([]string{"--prompt", "x", "--workspace", repo}, args...)) + if err != nil { + t.Fatalf("parseFlags: %v", err) + } + cfg := appConfig(f, port.NopDiagnostics{}, observability{}) + cfg.UseMock, cfg.NoSoul = true, true + return buildIsolated(t, context.Background(), cfg) + } + built, err := build(t, "--permission-config", settings, "--posture", "strict") + if err == nil { + built.Close() + t.Fatal("settings permissionMode plus --posture must refuse to build") + } + if !strings.Contains(err.Error(), "permissionMode: plan cannot be combined") || !strings.Contains(err.Error(), "--permission-mode default") { + t.Fatalf("refusal must name the conflict and the migration; got %v", err) + } + for _, tc := range []struct { + args []string + want session.PermissionMode + }{ + {[]string{"--permission-config", settings}, session.ModePlan}, + {[]string{"--posture", "strict"}, session.ModeDefault}, + } { + built, err := build(t, tc.args...) + if err != nil { + t.Fatalf("%q: app.Build: %v", tc.args, err) + } + sess, err := built.Service.CreateSession(context.Background(), "", session.Limits{}) + built.Close() + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + if sess.Mode != tc.want { + t.Fatalf("%q: unspecified-mode session started in %q, want %q", tc.args, sess.Mode, tc.want) + } + } +} diff --git a/cmd/mecatui/permission_mode_test.go b/cmd/mecatui/permission_mode_test.go index 3a8e68f1e9..08141c5f0c 100644 --- a/cmd/mecatui/permission_mode_test.go +++ b/cmd/mecatui/permission_mode_test.go @@ -2,6 +2,9 @@ package main import ( "context" + "io" + "os" + "path/filepath" "strings" "testing" "time" @@ -10,6 +13,8 @@ import ( "github.com/stacklok/mecatl/cmd/mecatui/embed" "github.com/stacklok/mecatl/cmd/mecatui/ui" "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/internal/app" ) @@ -224,3 +229,64 @@ func TestDefaultsReproduceCurrentBehaviour(t *testing.T) { }) } } + +// TestEmbeddedSettingsPermissionModeRefusesDeprecatedFlags drives the embedded +// server's real path (flags, embeddedConfig, app.Build) with a conventional +// user-global settings.yaml carrying permissionMode: plan. The deprecated +// --yolo and --posture flags cannot be combined with it; the token alone and +// the deprecated flag alone still build. +func TestEmbeddedSettingsPermissionModeRefusesDeprecatedFlags(t *testing.T) { + storage := isolatedEmbeddedTestStorage(t) + settings := filepath.Join(os.Getenv("XDG_CONFIG_HOME"), "mecatl", "settings.yaml") + build := func(t *testing.T, withSettings bool, args ...string) (*app.Built, error) { + t.Helper() + if withSettings { + if err := os.MkdirAll(filepath.Dir(settings), 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(settings, []byte("permissionMode: plan\n"), 0o600); err != nil { + t.Fatal(err) + } + } else if err := os.Remove(settings); err != nil && !os.IsNotExist(err) { + t.Fatal(err) + } + _, cfg, err := parseTransportFlags(modeLocal, io.Discard, append([]string{"--mock", "--workspace", t.TempDir()}, args...)) + if err != nil { + t.Fatalf("parse %v: %v", args, err) + } + ac := embeddedConfig(storage.apply(cfg), port.NopDiagnostics{}) + ac.NoSoul, ac.Privileged = true, false + return app.Build(t.Context(), ac) + } + for _, args := range [][]string{{"--yolo"}, {"--posture", "auto"}} { + built, err := build(t, true, args...) + if err == nil { + built.Close() + t.Fatalf("%q: settings permissionMode plus a deprecated flag must refuse to build", args) + } + if !strings.Contains(err.Error(), "permissionMode: plan cannot be combined") || !strings.Contains(err.Error(), "--permission-mode") { + t.Fatalf("%q: refusal must name the conflict and the migration; got %v", args, err) + } + } + for _, tc := range []struct { + withSettings bool + args []string + want session.PermissionMode + }{ + {true, nil, session.ModePlan}, + {false, []string{"--yolo"}, session.ModeYolo}, + } { + built, err := build(t, tc.withSettings, tc.args...) + if err != nil { + t.Fatalf("settings=%v %q: app.Build: %v", tc.withSettings, tc.args, err) + } + sess, err := built.Service.CreateSession(context.Background(), "", session.Limits{}) + built.Close() + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + if sess.Mode != tc.want { + t.Fatalf("settings=%v %q: unspecified-mode session started in %q, want %q", tc.withSettings, tc.args, sess.Mode, tc.want) + } + } +} diff --git a/internal/app/permission_mode.go b/internal/app/permission_mode.go index 7d6e18be62..49f848057b 100644 --- a/internal/app/permission_mode.go +++ b/internal/app/permission_mode.go @@ -97,28 +97,27 @@ func PermissionModeForPair(p Posture, mode session.PermissionMode) (PermissionMo // operator-tier posture: key, handled by foldOperatorPosture). A token writes // cfg.Posture, cfg.DefaultSessionMode, and cfg.MaxAllowedMode and marks the // posture explicit, so the deprecated posture: key cannot override it. -// --trust-project and --yolo still fold MAX-tier on top in resolvePosture, -// exactly as they do over --posture. +// The permissionMode: key combined with a deprecated --posture or --yolo flag +// is refused (settingsTokenAliasConflict), mirroring the cmd roots' refusal of +// --permission-mode with those flags. --trust-project is not deprecated and +// still folds MAX-tier on top in resolvePosture. func foldPermissionMode(cfg Config) (Config, error) { raw := "" source := "" - switch { - case cfg.PermissionModeFlagSet: + if cfg.PermissionModeFlagSet { raw, source = cfg.PermissionMode, "--permission-mode" - case cfg.PostureFlagSet: - // Deprecated --posture: the posture is already on cfg.Posture (set by the - // cmd layer); foldOperatorPosture would no-op since PostureFlagSet. The - // session mode and ceiling are NOT derived here: --yolo and --trust-project - // may still raise the posture, so Build derives them after the full alias - // fold. - return foldOperatorPosture(cfg), nil - default: - if res, ok := cfg.permResolver.(*permconfig.Resolver); ok && res != nil { - if v := strings.TrimSpace(res.OperatorPermissionMode()); v != "" { - raw, source = v, "settings permissionMode" + } else if res, ok := cfg.permResolver.(*permconfig.Resolver); ok && res != nil { + if v := strings.TrimSpace(res.OperatorPermissionMode()); v != "" { + if err := settingsTokenAliasConflict(cfg, v); err != nil { + return cfg, err } + raw, source = v, "settings permissionMode" } } + // Without a token, the deprecated --posture is already on cfg.Posture (set + // by the cmd layer) and foldOperatorPosture no-ops for it. The session mode + // and ceiling are NOT derived here: --yolo and --trust-project may still + // raise the posture, so Build derives them after the full alias fold. if source == "" { return foldOperatorPosture(cfg), nil } @@ -134,6 +133,33 @@ func foldPermissionMode(cfg Config) (Config, error) { return cfg, nil } +// settingsTokenAliasConflict refuses the operator-tier permissionMode: key +// combined with a deprecated --posture or --yolo flag. Either side alone names +// the posture; together the operator would have to guess which one won, and the +// --yolo MAX fold would raise the posture without the token's session mode and +// ceiling following it. The message names both ways to migrate. +func settingsTokenAliasConflict(cfg Config, token string) error { + var flags, replacements []string + if cfg.PostureFlagSet { + flags = append(flags, "--posture "+cfg.Posture.String()) + replacements = append(replacements, PostureReplacementToken(cfg.Posture)) + } + if cfg.AllowAllTools { + flags = append(flags, "--yolo") + replacements = append(replacements, PostureReplacementToken(PostureYolo)) + } + if len(flags) == 0 { + return nil + } + noun := "flag" + if len(flags) > 1 { + noun = "flags" + } + named := strings.Join(flags, " and ") + return fmt.Errorf("settings.yaml permissionMode: %s cannot be combined with the deprecated %s %s; pass one: drop %s and keep permissionMode: %s, or replace the deprecated %s with --permission-mode %s, which overrides the settings key", + token, named, noun, named, token, noun, replacements[len(replacements)-1]) +} + // PostureReplacementToken names the --permission-mode token that replaces a // deprecated posture value, so every root's deprecation warning names the same // replacement. trusted maps to default: its trust half is now --trust-project. diff --git a/user-docs/features/security-and-execution/permissions-and-posture.md b/user-docs/features/security-and-execution/permissions-and-posture.md index 470df6bfb9..6620fb29f5 100644 --- a/user-docs/features/security-and-execution/permissions-and-posture.md +++ b/user-docs/features/security-and-execution/permissions-and-posture.md @@ -175,7 +175,10 @@ terminal. key still work and resolve to the equivalent mode. Each logs a deprecation warning naming the `--permission-mode` replacement, and they will be removed in a future release. Passing `--permission-mode` together with `--posture`, -`--yolo`, or `--mode` is a startup error. `--trust-project` is not deprecated. +`--yolo`, or `--mode` is a startup error. So is passing `--posture` or `--yolo` +while your operator `settings.yaml` sets `permissionMode:`. Drop the deprecated +flag to keep the settings key, or replace it with `--permission-mode`, which +overrides the key. `--trust-project` is not deprecated. ## Auto needs an enforcing checker From fe699a28b6f37c198573cd78c9668dbac6e15a4f Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 16:47:07 +0300 Subject: [PATCH 41/48] test(permissions): execute a yolo, auto, default sequence on one session The existing auto-session guardrail test switched to auto before the first run, so it never proved the engine transitions between modes on a live session. This runs three completed turns on one session through the real composition, switching mode between runs: yolo runs the mutation with a rejecting checker consulted but advisory; auto lets that checker block it while a configured Deny still denies; default surfaces an ordinary permission ask instead of auto-allowing it. Co-Authored-By: Claude Opus 5.5 --- .../app/guardrails_approve_once_e2e_test.go | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/internal/app/guardrails_approve_once_e2e_test.go b/internal/app/guardrails_approve_once_e2e_test.go index 6b6ea0146d..84f3c8de72 100644 --- a/internal/app/guardrails_approve_once_e2e_test.go +++ b/internal/app/guardrails_approve_once_e2e_test.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "encoding/json" + "iter" "net/http" "net/http/httptest" "os" @@ -326,6 +327,150 @@ func TestGuardrailE2EYoloServerAutoSessionEnforces(t *testing.T) { } } +// modeRoutedProvider sends guardrail-reviewer requests (the GuardrailsModel) to +// reviewer and every other request to agent, so one session's agent script +// stays in order whether or not a mode consults the checker. +type modeRoutedProvider struct { + agent, reviewer *mockllm.Provider + reviewerModel string +} + +func (p modeRoutedProvider) Stream(ctx context.Context, req port.LLMRequest) (iter.Seq2[port.Chunk, error], error) { + if req.Model == p.reviewerModel { + return p.reviewer.Stream(ctx, req) + } + return p.agent.Stream(ctx, req) +} + +func (p modeRoutedProvider) Capabilities() port.ProviderCapabilities { return p.agent.Capabilities() } + +// modeTurnOutcome is what one executed turn surfaced. +type modeTurnOutcome struct { + policyAsks, guardrailAsks []string + results []session.ToolResult +} + +// runDenyingTurn runs one prompt to completion on the real service, denying +// every ask, and returns the asks (split by origin) and tool results. +func runDenyingTurn(t *testing.T, built *Built, id session.SessionID) modeTurnOutcome { + t.Helper() + run, err := built.Service.StartRun(context.Background(), id, "merge it") + if err != nil { + t.Fatalf("StartRun: %v", err) + } + var out modeTurnOutcome + for ev := range run.Events() { + if ev.Type == session.EvPermissionAsk && ev.Ask != nil { + if ev.Ask.Guardrail != nil { + out.guardrailAsks = append(out.guardrailAsks, ev.Ask.Tool) + } else { + out.policyAsks = append(out.policyAsks, ev.Ask.Tool) + } + run.Approve(ev.Ask.AskID, session.VerdictDeny) + } + if ev.Type == session.EvToolResult && ev.ToolResult != nil { + out.results = append(out.results, *ev.ToolResult) + } + } + built.Service.FinishRun(id, run) + return out +} + +// TestGuardrailE2EExecutedYoloAutoDefaultTransitions runs ONE session through +// three completed turns on a yolo server with a rejecting checker, switching +// mode between runs so the engine transitions live: yolo allows the mutation +// with the checker advisory; auto lets the same checker block it while a +// configured Deny still denies; default asks for it instead of auto-allowing. +func TestGuardrailE2EExecutedYoloAutoDefaultTransitions(t *testing.T) { + ctx := context.Background() + cfg := guardrailE2ECfg(t, true, PostureYolo, "") + settings := filepath.Join(t.TempDir(), "settings.yaml") + if err := os.WriteFile(settings, []byte("permissions:\n deny:\n - Write\n"), 0o600); err != nil { + t.Fatalf("write permission config: %v", err) + } + cfg.PermissionConfigs = []string{settings} + shell := func(id session.ToolCallID, marker string) mockllm.Turn { + return mockllm.ToolCallTurn(session.NewToolCall(id, "Shell", json.RawMessage(`{"command":"touch `+marker+`"}`))) + } + denied := filepath.Join(cfg.Workspace, "denied.txt") + agent := mockllm.New( + shell("y1", "yolo_marker"), mockllm.TextTurn("done"), + shell("a1", "auto_marker"), + mockllm.ToolCallTurn(session.NewToolCall("a2", "Write", json.RawMessage(`{"path":"`+denied+`","content":"x"}`))), + mockllm.TextTurn("done"), + shell("d1", "default_marker"), mockllm.TextTurn("done"), + ) + verdicts := make([]mockllm.Turn, 8) + for i := range verdicts { + verdicts[i] = guardrailE2EScript("")[1] + } + reviewer := mockllm.New(verdicts...) + cfg.providerConstructor = func(Config, string, string, string) port.LLMProvider { + return modeRoutedProvider{agent: agent, reviewer: reviewer, reviewerModel: cfg.GuardrailsModel} + } + built, err := buildIsolated(t, ctx, cfg) + if err != nil { + t.Fatalf("Build: %v", err) + } + defer built.Close() + sess, err := built.Service.CreateSession(ctx, session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + exists := func(name string) bool { + _, err := os.Stat(filepath.Join(cfg.Workspace, name)) + return err == nil + } + + // yolo: the mutation is auto-allowed and the rejecting checker is advisory. + yolo := runDenyingTurn(t, built, sess.ID) + if len(yolo.policyAsks)+len(yolo.guardrailAsks) != 0 || len(yolo.results) != 1 || yolo.results[0].IsError || !exists("yolo_marker") { + t.Fatalf("yolo turn: asks %v/%v results %+v marker %t; want the Shell call to run unasked", yolo.policyAsks, yolo.guardrailAsks, yolo.results, exists("yolo_marker")) + } + + if reviewer.Calls() == 0 { + t.Fatal("yolo turn: the checker was never consulted, so its advisory verdict proves nothing") + } + if _, err := built.Service.SetMode(ctx, sess.ID, session.ModeAuto); err != nil { + t.Fatalf("SetMode(auto) after a completed yolo run: %v", err) + } + // auto: no policy ask, but the same checker now blocks the mutation, and the + // configured Deny still denies Write without an ask. + auto := runDenyingTurn(t, built, sess.ID) + if len(auto.policyAsks) != 0 || len(auto.guardrailAsks) != 1 || auto.guardrailAsks[0] != "Shell" { + t.Fatalf("auto turn asks: policy %v guardrail %v; want exactly one guardrail ask for Shell", auto.policyAsks, auto.guardrailAsks) + } + if exists("auto_marker") { + t.Fatal("auto turn: the checker-blocked Shell command ran") + } + if len(auto.results) != 2 || !auto.results[0].IsError || !auto.results[1].IsError { + t.Fatalf("auto turn results = %+v; want the blocked Shell and denied Write as errors", auto.results) + } + if _, err := os.Stat(denied); !os.IsNotExist(err) { + t.Fatalf("auto turn: configured Deny let Write land (stat err %v)", err) + } + + if _, err := built.Service.SetMode(ctx, sess.ID, session.ModeDefault); err != nil { + t.Fatalf("SetMode(default) after a completed auto run: %v", err) + } + // default: the mutation is not auto-allowed; it surfaces as an ordinary + // permission ask, and the denied command never runs. + def := runDenyingTurn(t, built, sess.ID) + if len(def.policyAsks) == 0 || def.policyAsks[0] != "Shell" { + t.Fatalf("default turn asks: policy %v guardrail %v; want an ordinary Shell permission ask", def.policyAsks, def.guardrailAsks) + } + if exists("default_marker") { + t.Fatal("default turn: the denied Shell command ran") + } + final, err := built.Service.GetSession(ctx, sess.ID) + if err != nil { + t.Fatalf("GetSession: %v", err) + } + if final.Mode != session.ModeDefault || final.State != session.StateCompleted { + t.Fatalf("final session mode %q state %q, want default/completed", final.Mode, final.State) + } +} + // Posture YOLO: guardrails demote to advisory — the tool RUNS, no ask, no block. func TestGuardrailApproveOnceE2EYoloAdvisory(t *testing.T) { ctx := context.Background() From 5b5f3ae744037f8f843194eb54cf602177f645f9 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 17:48:10 +0300 Subject: [PATCH 42/48] fix(permissions): adopt the under-lease snapshot at run entry admitLeasedMode validated the snapshot loaded under the lease but threw it away, so the entry continued with its pre-lease copy. An admitted change a peer made while this replica waited for the lease was then lost: a completed session downgraded from yolo to default was reopened and saved back as yolo, and an approval resume could resume a pending ask the peer had already cancelled through the refused-mode recovery. adoptLeasedSession now returns the authoritative aggregate, re-admits its mode, and installs it as st.sess. StartRunContent, RetryFailedRun, and the awaiting approval resume continue with it and repeat their own state, run, and ask gates before any recovery, persistence, or execution. The existing reload re-admission and launch fences stay. Without a shared lease the pre-lease snapshot is already authoritative, since every in-process writer serializes on runEntryMu, so adoption is a no-op there. Co-Authored-By: Claude Opus 5.5 --- .../adapter/server/mode_admission_test.go | 138 +++++++++++++++++ internal/adapter/server/mode_recovery_test.go | 9 +- internal/adapter/server/service.go | 143 +++++++++++++----- 3 files changed, 249 insertions(+), 41 deletions(-) diff --git a/internal/adapter/server/mode_admission_test.go b/internal/adapter/server/mode_admission_test.go index 141f4651c3..90f139cdbc 100644 --- a/internal/adapter/server/mode_admission_test.go +++ b/internal/adapter/server/mode_admission_test.go @@ -8,6 +8,7 @@ import ( "net/http/httptest" "strings" "sync" + "sync/atomic" "testing" "time" @@ -409,6 +410,143 @@ func TestStoredModeReadmittedUnderAcquiredLease(t *testing.T) { } } +// gatedLeaseFor wraps a fresh shared memlease so owner's first Acquire parks +// until the test releases it. +func gatedLeaseFor(owner string) *gatedLease { + return &gatedLease{ + SessionLease: memlease.New(wallclock.Clock{}, time.Minute), + owner: owner, entered: make(chan struct{}), release: make(chan struct{}), + } +} + +// awaitGate waits until the gated owner is parked at lease acquisition. +func awaitGate(t *testing.T, lease *gatedLease) { + t.Helper() + select { + case <-lease.entered: + case <-time.After(5 * time.Second): + t.Fatal("the gated replica never reached lease acquisition") + } +} + +// TestRunEntryAdoptsAdmittedDowngradeUnderLease is the admitted-downgrade +// variant of TestStoredModeReadmittedUnderAcquiredLease: both replicas admit +// yolo, so mode admission alone cannot catch the race. Replica A reads a +// completed yolo session and waits for the lease; replica B downgrades it to +// default and releases; A must then run on the adopted default snapshot and +// must not reopen and save its stale yolo copy over B's change. +func TestRunEntryAdoptsAdmittedDowngradeUnderLease(t *testing.T) { + ctx := context.Background() + store := memstore.New() + seed := modeAdmissionServiceOn(t, store, mockllm.New(mockllm.TextTurn("first")), session.ModeYolo, session.ModeDefault, true) + sess, err := seed.CreateSession(ctx, session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + first, err := seed.StartRun(ctx, sess.ID, "first") + if err != nil { + t.Fatalf("seed StartRun: %v", err) + } + for range first.Events() { + } + seed.Persist(ctx, sess.ID) + seed.FinishRun(sess.ID, first) + if done, err := store.Load(ctx, sess.ID); err != nil || done.State != session.StateCompleted || done.Mode != session.ModeYolo { + t.Fatalf("seeded session = %+v, %v; want a completed yolo session", done, err) + } + + lease := gatedLeaseFor("replica-a") + llmA := mockllm.New(mockllm.TextTurn("second")) + a := leasedModeService(t, store, lease, "replica-a", llmA, session.ModeYolo) + b := leasedModeService(t, store, lease, "replica-b", mockllm.New(), session.ModeYolo) + + result := make(chan error, 1) + go func() { + run, err := a.StartRun(ctx, sess.ID, "second") + if run != nil { + for range run.Events() { + } + a.Persist(ctx, sess.ID) + a.FinishRun(sess.ID, run) + } + result <- err + }() + awaitGate(t, lease) + if _, err := b.SetMode(ctx, sess.ID, session.ModeDefault); err != nil { + t.Fatalf("peer SetMode(default): %v", err) + } + close(lease.release) + select { + case err := <-result: + if err != nil { + t.Fatalf("StartRun on the downgraded session: %v", err) + } + case <-time.After(5 * time.Second): + t.Fatal("replica A StartRun did not return") + } + if llmA.Calls() != 1 { + t.Fatalf("replica A provider calls = %d, want 1", llmA.Calls()) + } + after, err := store.Load(ctx, sess.ID) + if err != nil { + t.Fatalf("Load: %v", err) + } + if after.Mode != session.ModeDefault || after.State != session.StateCompleted { + t.Fatalf("after A's run: mode %q state %q; want B's default downgrade kept and the run completed", after.Mode, after.State) + } +} + +// TestApprovalResumeAdoptsPeerCancelledTurnUnderLease: replica A preflights an +// approval for a pending ask and waits for the lease; replica B, which refuses +// the stored yolo mode, cancels that pending turn through the refused-mode +// SetMode downgrade and releases. A must refuse the resume on the adopted +// snapshot with no provider or tool work, leaving B's cancellation in place. +func TestApprovalResumeAdoptsPeerCancelledTurnUnderLease(t *testing.T) { + ctx := context.Background() + store := memstore.New() + id, askID := parkAwaitingInMode(t, store, session.ModeYolo) + + lease := gatedLeaseFor("replica-a") + var ranA, ranB atomic.Int64 + llmA := mockllm.New(mockllm.TextTurn("resumed")) + a := recoveryServiceAs(t, store, llmA, &ranA, session.ModeYolo, true, lease, "replica-a") + b := recoveryServiceAs(t, store, mockllm.New(), &ranB, session.ModeAccept, true, lease, "replica-b") + + result := make(chan error, 1) + go func() { + run, err := a.ApproveRun(ctx, id, askID, session.VerdictAllowOnce, "") + if run != nil { + for range run.Events() { + } + a.FinishRun(id, run) + } + result <- err + }() + awaitGate(t, lease) + if _, err := b.SetMode(ctx, id, session.ModeDefault); err != nil { + t.Fatalf("peer refused-mode recovery SetMode(default): %v", err) + } + close(lease.release) + select { + case err := <-result: + if !errors.Is(err, server.ErrNoActiveRun) { + t.Fatalf("ApproveRun err = %v, want ErrNoActiveRun for the cancelled turn", err) + } + case <-time.After(5 * time.Second): + t.Fatal("replica A ApproveRun did not return") + } + if llmA.Calls() != 0 || ranA.Load() != 0 || ranB.Load() != 0 { + t.Fatalf("work ran after the peer cancelled: provider calls %d, tool executions A=%d B=%d", llmA.Calls(), ranA.Load(), ranB.Load()) + } + kept, err := store.Load(ctx, id) + if err != nil { + t.Fatalf("Load: %v", err) + } + if _, pending := kept.PendingAsk(); pending || kept.State != session.StateCancelled || kept.Mode != session.ModeDefault { + t.Fatalf("stored after refused resume: mode %q state %q pending %t; want cancelled/default", kept.Mode, kept.State, pending) + } +} + // TestHTTPAutoYoloModes pins the HTTP mode mapping and the shared admission. func TestHTTPAutoYoloModes(t *testing.T) { decode := func(resp *http.Response) (int, string) { diff --git a/internal/adapter/server/mode_recovery_test.go b/internal/adapter/server/mode_recovery_test.go index 3b785a1824..0b21a299a5 100644 --- a/internal/adapter/server/mode_recovery_test.go +++ b/internal/adapter/server/mode_recovery_test.go @@ -50,6 +50,13 @@ func parkAwaitingInMode(t *testing.T, store port.SessionStore, stored session.Pe // recoveryService is a restarted deployment over store with the given ceiling // and checker; lease, when non-nil, is shared with a peer. func recoveryService(t *testing.T, store port.SessionStore, llm *mockllm.Provider, ran *atomic.Int64, ceiling session.PermissionMode, checker bool, lease port.SessionLease) *server.Service { + t.Helper() + return recoveryServiceAs(t, store, llm, ran, ceiling, checker, lease, "recovering") +} + +// recoveryServiceAs is recoveryService with an explicit lease owner, so two +// replicas can share one lease backend. +func recoveryServiceAs(t *testing.T, store port.SessionStore, llm *mockllm.Provider, ran *atomic.Int64, ceiling session.PermissionMode, checker bool, lease port.SessionLease, owner string) *server.Service { t.Helper() cat := tool.NewCatalog() cat.MustRegister(&writeAskTool{ran: ran}) @@ -61,7 +68,7 @@ func recoveryService(t *testing.T, store port.SessionStore, llm *mockllm.Provide EnforcingCheckerConfigured: checker, } if lease != nil { - cfg.SessionLease, cfg.LeaseOwner, cfg.LeaseTTL, cfg.LeaseRenewInterval = lease, "recovering", time.Minute, time.Hour + cfg.SessionLease, cfg.LeaseOwner, cfg.LeaseTTL, cfg.LeaseRenewInterval = lease, owner, time.Minute, time.Hour } svc, err := newPlacementTestService(cfg) if err != nil { diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index 9db1e23769..1a0245e236 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -4919,25 +4919,42 @@ func (s *Service) cancelRefusedAwaiting(sess *session.Session, mode session.Perm return nil } -// admitLeasedMode re-admits the AUTHORITATIVE stored mode once this process -// holds id's session lease. beginRunAdmission checked the pre-lease snapshot -// only: while this request waited for the lease, a peer on a looser -// configuration (a rolling upgrade) may have taken the lease and saved a mode -// this server does not admit. The caller holds runEntryMu and the lease, so -// the snapshot read here is the one any later reload observes; every later -// replacement of the run's aggregate re-admits it, and the launch fences -// check the executed aggregate once more. -func (s *Service) admitLeasedMode(ctx context.Context, id session.SessionID) error { +// adoptLeasedSession replaces a run entry's pre-lease snapshot with the +// AUTHORITATIVE one once this process holds id's session lease, re-admits its +// mode, and adopts it as the run's aggregate (st.sess). The pre-lease snapshot +// was only a preflight: while this request waited for the lease, a peer may +// have saved the session, e.g. downgraded its mode or cancelled its pending +// turn, and continuing with the stale copy would execute or persist over that +// change. The caller must repeat its entry-specific state, run, and ask checks +// against the returned aggregate before any recovery effect, persistence, or +// execution. Every later replacement of the aggregate re-admits it, and the +// launch fences check the executed aggregate once more. +// +// Without a shared lease it returns sess unchanged: there is no peer writer, +// and every in-process writer of a session (run entry, SetMode, management +// operations) serializes on runEntryMu, which the caller held across the +// pre-lease load. +func (s *Service) adoptLeasedSession(ctx context.Context, id session.SessionID, st *runState, sess *session.Session) (*session.Session, error) { if s.cfg.SessionLease == nil { - // Without a shared lease there is no peer writer to race; the - // pre-lease snapshot was read under runEntryMu. - return nil + return sess, nil } - sess, err := s.cfg.Store.Load(ctx, id) + loaded, err := s.GetSession(ctx, id) if err != nil { - return fmt.Errorf("%w: %q", ErrNotFound, id) + return nil, err + } + if err := s.admitStoredMode(loaded); err != nil { + return nil, err } - return s.admitStoredMode(sess) + st.persistMu.Lock() + defer st.persistMu.Unlock() + s.mu.Lock() + defer s.mu.Unlock() + if s.runs[id] != st || st.cancelling || st.cancelSignaled { + return nil, fmt.Errorf("%w: %q", ErrUnavailable, id) + } + st.sess = loaded + st.titleRevision = loaded.TitleRevision + return loaded, nil } // modeWithinCeiling reports whether mode is at or below ceiling in the @@ -5529,6 +5546,8 @@ func (s *Service) StartScheduledRunContent(ctx context.Context, id session.Sessi // FinishRun, exactly as for StartRunContent. Eligibility is derived exclusively from the // persisted typed terminal metadata and is consumed only after every fallible setup step // has succeeded and the recovered idle snapshot has been saved. +// +//nolint:gocyclo // Retry entry keeps preflight, lease, adopted-snapshot gates, and launch in one ordered transaction. func (s *Service) RetryFailedRun(ctx context.Context, id session.SessionID) (*agent.Run, error) { generation := s.captureRunEntryGeneration(id) if s.draining.Load() { @@ -5558,9 +5577,8 @@ func (s *Service) RetryFailedRun(ctx context.Context, id session.SessionID) (*ag if err := s.deregisterTerminalRunForEntry(id, sess, ErrFailedStepRetryIneligible); err != nil { return nil, err } - eligibleFailure, err := failedStepRetryEligibility(sess) - if err != nil { - return nil, fmt.Errorf("%w: session %q: %v", ErrFailedStepRetryIneligible, id, err) + if _, err := s.retryEntryEligibility(id, sess); err != nil { + return nil, err } st, admissionParent, err := s.beginRunAdmission(ctx, id, sess, false) @@ -5579,7 +5597,13 @@ func (s *Service) RetryFailedRun(ctx context.Context, id session.SessionID) (*ag } }() ctx = admissionCtx - if err := s.admitLeasedMode(ctx, id); err != nil { + if sess, err = s.adoptLeasedSession(ctx, id, st, sess); err != nil { + return nil, err + } + // Repeat the retry gates against the adopted aggregate: a peer may have + // retried, recovered, or otherwise moved the session on. + eligibleFailure, err := s.retryEntryEligibility(id, sess) + if err != nil { return nil, err } engine, env, governanceRoot, err := s.engineAndEnvironmentFor(ctx, sess) @@ -5615,6 +5639,23 @@ func (s *Service) RetryFailedRun(ctx context.Context, id session.SessionID) (*ag return run, nil } +// retryEntryEligibility is RetryFailedRun's entry gate, run on the preflight +// snapshot and again on the aggregate adopted under the lease. It reports +// whether the session is still in its failed terminal (versus a prepared retry). +func (s *Service) retryEntryEligibility(id session.SessionID, sess *session.Session) (bool, error) { + if err := s.validatePersistedWorkspace(sess); err != nil { + return false, err + } + if err := admitRunPurpose(sess, runPurposeChat); err != nil { + return false, fmt.Errorf("%w: session %q is not eligible for chat retry", ErrFailedStepRetryIneligible, id) + } + eligibleFailure, err := failedStepRetryEligibility(sess) + if err != nil { + return false, fmt.Errorf("%w: session %q: %v", ErrFailedStepRetryIneligible, id, err) + } + return eligibleFailure, nil +} + func failedStepRetryEligibility(sess *session.Session) (bool, error) { metadata := sess.FailureMetadata() pendingMetadata, pending := sess.FailedStepRetryPending() @@ -5807,9 +5848,20 @@ func (s *Service) startRunContentLocked(ctx context.Context, id session.SessionI } }() ctx = admissionCtx - if err := s.admitLeasedMode(ctx, id); err != nil { + if sess, err = s.adoptLeasedSession(ctx, id, st, sess); err != nil { return nil, err } + // Repeat the entry gates against the adopted aggregate before recovery can + // mutate or persist it. + if err := s.validatePersistedWorkspace(sess); err != nil { + return nil, err + } + if err := admitRunPurpose(sess, purpose); err != nil { + return nil, err + } + if _, pending := sess.FailedStepRetryPending(); pending { + return nil, fmt.Errorf("%w: session %q has a pending failed-step retry", ErrFailedPrecondition, id) + } // Apply the unchanged reopen/interrupt/recover funnel only after the trusted // purpose and ownership gates and lease acquisition. Rejected kinds are never // mutated as a side effect of probing. @@ -7620,6 +7672,30 @@ func (s *Service) ResolveApprovalRun(ctx context.Context, id session.SessionID, return s.resumeFromAwaiting(ctx, id, resolution, expectedRunID, generation) } +// validateAwaitingResume is resumeFromAwaiting's exact-run/ask proof, run on +// the preflight snapshot and again on the aggregate adopted under the lease. +func (s *Service) validateAwaitingResume(sess *session.Session, resolution agent.ApprovalResolution, expectedRunID string) error { + if err := s.validatePersistedWorkspace(sess); err != nil { + return err + } + // On this path the persisted session IS the run — it parked awaiting the ask + // and no live *agent.Run exists — so the stored id is the authoritative answer + // to "which run would this verdict resolve?". + if err := checkExpectedRun(expectedRunID, sess.RunID()); err != nil { + return err + } + if sess.State != session.StateAwaiting { + // Awaiting is the only resumable non-terminal state. Everything else stays + // stranded-for-Approve (last-write-wins / nothing to resume). + return ErrNoActiveRun + } + pending, ok := sess.PendingAsk() + if !ok || pending.AskID != resolution.AskID { + return fmt.Errorf("%w: ask is unknown, stale, or already resolved", agent.ErrApprovalNotPending) + } + return agent.ValidateApprovalResolution(pending, resolution) +} + // resumeFromAwaiting is the service half of the fourth (awaiting-only) run-entry // seam: it handles an Approve/Deny against a session whose process died while parked // awaiting approval. It loads the persisted session and: @@ -7688,25 +7764,7 @@ func (s *Service) resumeFromAwaiting(ctx context.Context, id session.SessionID, if err != nil { return nil, err } - if err := s.validatePersistedWorkspace(sess); err != nil { - return nil, err - } - // On this path the persisted session IS the run — it parked awaiting the ask - // and no live *agent.Run exists — so the stored id is the authoritative answer - // to "which run would this verdict resolve?". - if err := checkExpectedRun(expectedRunID, sess.RunID()); err != nil { - return nil, err - } - if sess.State != session.StateAwaiting { - // Awaiting is the only resumable non-terminal state. Everything else stays - // stranded-for-Approve (last-write-wins / nothing to resume). - return nil, ErrNoActiveRun - } - pending, ok := sess.PendingAsk() - if !ok || pending.AskID != resolution.AskID { - return nil, fmt.Errorf("%w: ask is unknown, stale, or already resolved", agent.ErrApprovalNotPending) - } - if err := agent.ValidateApprovalResolution(pending, resolution); err != nil { + if err := s.validateAwaitingResume(sess, resolution, expectedRunID); err != nil { return nil, err } st, admissionParent, err := s.beginRunAdmission(ctx, id, sess, true) @@ -7728,7 +7786,12 @@ func (s *Service) resumeFromAwaiting(ctx context.Context, id session.SessionID, } }() ctx = admissionCtx - if err := s.admitLeasedMode(ctx, id); err != nil { + // The pre-lease snapshot was a preflight: a peer may have resumed, cancelled, + // or recovered the pending turn while this request waited for the lease. + if sess, err = s.adoptLeasedSession(ctx, id, st, sess); err != nil { + return nil, err + } + if err := s.validateAwaitingResume(sess, resolution, expectedRunID); err != nil { return nil, err } if err := s.attachLiveInstructions(sess, true); err != nil { From 61490c398c4f724f7dfef800b7c763da2c0ae622 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 17:51:47 +0300 Subject: [PATCH 43/48] test(permissions): give the Team checker fixture a well-formed prohibited verdict The fixture's concerns were bare strings, which the reviewer rejects as a malformed assessment. The narrower member was then blocked by fail-closed parsing, not by a prohibited verdict, so the test did not prove what it claimed. The verdict now carries a schema-valid concern, and the action case asserts the reason reserved for a parsed prohibited assessment; with the old fixture that assertion fails. Co-Authored-By: Claude Opus 5.5 --- internal/app/child_mode_guardrail_test.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/app/child_mode_guardrail_test.go b/internal/app/child_mode_guardrail_test.go index 29ac270a76..c19e58e21b 100644 --- a/internal/app/child_mode_guardrail_test.go +++ b/internal/app/child_mode_guardrail_test.go @@ -19,15 +19,19 @@ import ( // its yolo parent. func TestYoloParentNarrowerTeamMemberKeepsEnforcingChecker(t *testing.T) { const canary = "MEMBER-READ-CANARY" - const prohibited = `{"assessment":"prohibited","concerns":["unsafe"],"evidence":[],"missing_evidence":[]}` + const prohibited = `{"assessment":"prohibited","concerns":[{"ref":"C1","category":"data_exfiltration","rationale":"member read is unsafe","source_ref":"call"}],"evidence":[],"missing_evidence":[]}` + // wantReason pins how the narrower member was stopped. For the action + // review it names a PARSED prohibited verdict; a malformed verdict fails + // closed with "could not approve this action" instead. for _, tc := range []struct { name, phase, agent string wantLeak bool + wantReason string }{ - {"action-narrow", "pre", "narrow", false}, - {"action-inherit", "pre", "", true}, - {"inbound-narrow", "post", "narrow", false}, - {"inbound-inherit", "post", "", true}, + {"action-narrow", "pre", "narrow", false, "contextual guardrail requires human approval for this action"}, + {"action-inherit", "pre", "", true, ""}, + {"inbound-narrow", "post", "narrow", false, "tool result withheld by contextual guardrail"}, + {"inbound-inherit", "post", "", true, ""}, } { t.Run(tc.name, func(t *testing.T) { workspace := t.TempDir() @@ -98,6 +102,9 @@ func TestYoloParentNarrowerTeamMemberKeepsEnforcingChecker(t *testing.T) { if leaked := strings.Contains(read.Content, canary); leaked != tc.wantLeak { t.Fatalf("member Read result leaked=%t, want %t (enforcement must follow the member's own mode): %q", leaked, tc.wantLeak, read.Content) } + if tc.wantReason != "" && !strings.Contains(read.Content, tc.wantReason) { + t.Fatalf("member Read result = %q, want the reason %q", read.Content, tc.wantReason) + } }) } } From 177789dbb5426e13b4f344eb9e52317a8cfa7a79 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 17:59:31 +0300 Subject: [PATCH 44/48] fix(schedule): fire a mutating in-chat schedule in its creator's mode The Schedule tool always recorded a mutating schedule as ModeDefault. That was harmless while yolo was a process-wide posture. Now that the permission mode belongs to each session, a schedule created from a yolo session fired into a default session. Its Write then asked for approval with no approver, so the fire hung until its deadline. This is the kind TestKindExecutionBorrowedSchedule hang. Dispatch now stamps the executing session's mode on each tool call's context, read at execution like parentCaps' parentMode. The tool records that mode for a mutating create. It never reads the mode from model arguments. Read-leaning schedules still record plan. An unbound context keeps ModeDefault. A plan-mode context refuses the mutating create. The fire path already admits the recorded mode in CreateSessionWithProfile. So a schedule recorded in yolo on a server later relaunched with a lower ceiling fails fast as a StopError fire instead of escalating or hanging. The new composition test covers both the yolo fire and the refused fire. Co-Authored-By: Claude Opus 5.5 --- engine/CHANGELOG.md | 9 ++ engine/agent/dispatch.go | 5 + engine/agent/export_test.go | 5 + engine/agent/scheduletool.go | 19 ++- engine/agent/scheduletool_test.go | 86 ++++++++++++ engine/agent/sessionorigin.go | 21 +++ internal/app/scheduler_fire.go | 6 +- internal/app/scheduler_fire_mode_test.go | 131 ++++++++++++++++++ .../features/sessions/scheduled-tasks.md | 5 + 9 files changed, 283 insertions(+), 4 deletions(-) create mode 100644 internal/app/scheduler_fire_mode_test.go diff --git a/engine/CHANGELOG.md b/engine/CHANGELOG.md index 1055a2f32a..874e969b08 100644 --- a/engine/CHANGELOG.md +++ b/engine/CHANGELOG.md @@ -459,6 +459,15 @@ The covered surface is the eight core packages (`session`, `governance`, `learni parent: it runs in the narrower of its stored mode and the mode a fresh child would get. No signature changes. +- **Mutating in-chat schedules fire in their creator's mode** — a + `mutating: true` schedule created through the `Schedule` tool now records the + executing session's permission mode as `ScheduleSpec.Mode` instead of always + `ModeDefault`. A yolo session's schedule therefore fires in yolo rather than + in a default session whose writes ask with no approver. Read-leaning + schedules still record `ModePlan`, and an unbound context still records + `ModeDefault`. The host re-admits the recorded mode at every fire. No + signature changes. + - **Contextual review enforcement follows the executing session's mode** — the engine now demotes a `ReviewPolicyProvider`'s enforcement to advisory for an executing `ModeYolo` session, and never consults diff --git a/engine/agent/dispatch.go b/engine/agent/dispatch.go index 0dc27f5ea8..5ffad3848d 100644 --- a/engine/agent/dispatch.go +++ b/engine/agent/dispatch.go @@ -2058,6 +2058,11 @@ func (e *Engine) timeExecute(ctx context.Context, r *Run, sess *session.Session, ev.Turn = turnIdx r.children.safeEmit(ev) } + if sess != nil { + // Read at execution, like parentCaps' parentMode, so a schedule created + // after a mid-session mode change records the mode it was created under. + ctx = withSessionMode(ctx, sess.Mode) + } switch ct := t.(type) { case childCapableTool: // Child-capable tools may execute in read-batch workers. Keep their returned diff --git a/engine/agent/export_test.go b/engine/agent/export_test.go index 559ba0ee7a..c4dadf23e4 100644 --- a/engine/agent/export_test.go +++ b/engine/agent/export_test.go @@ -11,6 +11,11 @@ import "github.com/stacklok/mecatl/engine/session" // test-only on purpose — see the withSessionOrigin doc-comment. var WithSessionOrigin = withSessionOrigin +// WithSessionMode exposes withSessionMode so the external tests can pin the +// schedule tool's handling of a context the dispatch stamp cannot produce for +// it (a plan-mode session holding the non-plan tool). +var WithSessionMode = withSessionMode + // EnqueueSteerForTest exposes the canonical Run steer entry point to external // drain tests. var EnqueueSteerForTest = (*Run).EnqueueSteer diff --git a/engine/agent/scheduletool.go b/engine/agent/scheduletool.go index 84fef0678c..bfbcb66265 100644 --- a/engine/agent/scheduletool.go +++ b/engine/agent/scheduletool.go @@ -370,9 +370,22 @@ func (t *ScheduleTool) create(ctx context.Context, call session.ToolCall, args s if err != nil { return session.NewToolError(call.ID, "Schedule create: "+err.Error()) } - mode := session.ModeDefault - if !args.Mutating { - mode = session.ModePlan + // A read-leaning schedule always fires in plan (the Mutating/Mode + // invariant). A mutating one fires in the CREATING session's mode, read + // from the run context and never from args: a yolo session's schedule must + // not fire into a default session whose writes ask with no approver. The + // fire re-admits that mode against the server's ceiling, so a server + // tightened after creation refuses the fire rather than escalating it. An + // unbound context (no executing session) keeps the conservative default. + mode := session.ModePlan + if args.Mutating { + mode = sessionModeFromContext(ctx) + if mode == "" { + mode = session.ModeDefault + } + if mode == session.ModePlan { + return session.NewToolError(call.ID, "Schedule create: plan mode is active: a mutating Schedule create is not permitted; present a plan and exit plan mode first") + } } origin := sessionOriginFromContext(ctx) spec := port.ScheduleSpec{ diff --git a/engine/agent/scheduletool_test.go b/engine/agent/scheduletool_test.go index 5c1df23eca..96e24a4519 100644 --- a/engine/agent/scheduletool_test.go +++ b/engine/agent/scheduletool_test.go @@ -3,14 +3,18 @@ package agent_test import ( "context" "errors" + "fmt" "strings" "testing" "time" "github.com/stacklok/mecatl/engine/adapter/memfs" + "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/port" "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/engine/tool" ) // scheduletool_test.go pins the ScheduleTool's in-engine behaviour: the verb @@ -647,3 +651,85 @@ func TestScheduleTool_InspectRendersTerminalFire(t *testing.T) { t.Fatalf("terminal inspect rendered \"in-flight\" = %q (a terminal fire must NOT render the in-flight marker)", res.Content) } } + +// TestScheduleTool_MutatingCreateRecordsCreatingSessionMode pins that a mutating +// in-chat schedule fires in the mode of the session that created it, stamped by +// dispatch from the executing session through a real Engine.Run, while a +// read-leaning schedule records plan whatever the creating mode. Recording a +// fixed default instead made a yolo session's schedule fire into a default +// session whose writes ask with no approver, hanging the fire. +func TestScheduleTool_MutatingCreateRecordsCreatingSessionMode(t *testing.T) { + t.Parallel() + cases := []struct { + name string + mode session.PermissionMode + mutating bool + want session.PermissionMode + }{ + {name: "default mutating", mode: session.ModeDefault, mutating: true, want: session.ModeDefault}, + {name: "accept-edits mutating", mode: session.ModeAccept, mutating: true, want: session.ModeAccept}, + {name: "yolo mutating", mode: session.ModeYolo, mutating: true, want: session.ModeYolo}, + {name: "yolo read-leaning", mode: session.ModeYolo, mutating: false, want: session.ModePlan}, + {name: "default read-leaning", mode: session.ModeDefault, mutating: false, want: session.ModePlan}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + args := fmt.Sprintf(`{"verb":"create","name":"s","prompt":"p","cron":"@every 1h","mutating":%t}`, tc.mutating) + llm := mockllm.New( + mockllm.ToolCallTurn(toolCall("c1", agent.ScheduleToolName, args)), + mockllm.TextTurn("done"), + ) + mgr := newStubScheduleManager() + cat := tool.NewCatalog() + cat.MustRegister(agent.NewScheduleTool(mgr)) + eng := agent.NewEngine(agent.Deps{ + LLM: llm, + Catalog: cat, + Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), + }) + sess := session.New("creator", tc.mode, session.EnvironmentRef{Kind: session.EnvKindLocal, ID: "/ws", Revision: "in-tree-v1"}, session.Limits{}, time.Unix(0, 0)) + drain(eng.Run(context.Background(), sess, agent.MemEnv("/ws"), agent.RunRequest{Text: "schedule it"})) + + if len(mgr.created) != 1 { + t.Fatalf("created %d schedules, want 1", len(mgr.created)) + } + got := mgr.created[0] + if got.Mode != tc.want || got.Mutating != tc.mutating { + t.Fatalf("recorded (mode %q, mutating %t), want (mode %q, mutating %t)", got.Mode, got.Mutating, tc.want, tc.mutating) + } + }) + } +} + +// TestScheduleTool_MutatingCreateModeFallbacks pins the two contexts the +// dispatch stamp does not cover: an unbound context (no executing session) +// keeps the conservative default, and a plan-mode context holding the non-plan +// tool refuses the mutating create rather than recording a mutating plan-mode +// schedule that could never write. +func TestScheduleTool_MutatingCreateModeFallbacks(t *testing.T) { + t.Parallel() + create := `{"verb":"create","name":"s","prompt":"p","cron":"@every 1h","mutating":true}` + + mgr := newStubScheduleManager() + res, err := agent.NewScheduleTool(mgr).Execute(context.Background(), scheduleCall(t, create), agent.MemEnv("/ws")) + if err != nil || res.IsError { + t.Fatalf("unbound mutating create = (%v, %q), want allowed", err, res.Content) + } + if len(mgr.created) != 1 || mgr.created[0].Mode != session.ModeDefault { + t.Fatalf("unbound mutating create recorded %+v, want mode %q", mgr.created, session.ModeDefault) + } + + mgr = newStubScheduleManager() + ctx := agent.WithSessionMode(context.Background(), session.ModePlan) + res, err = agent.NewScheduleTool(mgr).Execute(ctx, scheduleCall(t, create), agent.MemEnv("/ws")) + if err != nil { + t.Fatalf("plan-context Execute: %v", err) + } + if !res.IsError || !strings.Contains(res.Content, "plan mode") { + t.Fatalf("plan-context mutating create = %q, want the plan-mode refusal", res.Content) + } + if len(mgr.created) != 0 { + t.Fatalf("plan-context mutating create reached the manager: %+v", mgr.created) + } +} diff --git a/engine/agent/sessionorigin.go b/engine/agent/sessionorigin.go index f3511ff5ec..143ae3dbb8 100644 --- a/engine/agent/sessionorigin.go +++ b/engine/agent/sessionorigin.go @@ -37,3 +37,24 @@ func sessionOriginFromContext(ctx context.Context) session.SessionID { id, _ := ctx.Value(sessionOriginContextKey{}).(session.SessionID) return id } + +type sessionModeContextKey struct{} + +// withSessionMode returns a child context carrying the executing session's +// permission mode at the moment a tool call executes. Its one writer is +// timeExecute, which stamps sess.Mode per call (not once per run) because the +// mode can change between dispatches; its one reader is ScheduleTool.create, +// which records it as a mutating schedule's fire mode. Unexported for the same +// reason as withSessionOrigin: the mode must come from the run, never from an +// embedder or from model arguments, or a schedule could name a mode its +// creating session never held. +func withSessionMode(ctx context.Context, mode session.PermissionMode) context.Context { + return context.WithValue(ctx, sessionModeContextKey{}, mode) +} + +// sessionModeFromContext reads the executing session's mode, returning the +// empty mode when the context did not come from timeExecute. +func sessionModeFromContext(ctx context.Context) session.PermissionMode { + mode, _ := ctx.Value(sessionModeContextKey{}).(session.PermissionMode) + return mode +} diff --git a/internal/app/scheduler_fire.go b/internal/app/scheduler_fire.go index 4879d7eed2..e6decccba2 100644 --- a/internal/app/scheduler_fire.go +++ b/internal/app/scheduler_fire.go @@ -73,7 +73,11 @@ func makeFireFuncWithCancel(svc *server.Service, store port.ScheduleStore, defau // mutating (Mutating=true) honors its explicit Mode (or the server's // DefaultMode when unset, which reflects the operator's permission // configuration — for allow-all deployments this is ModeAuto or ModeYolo). - // Passing "" to CreateSessionWithProfile falls back to s.cfg.DefaultMode. + // The in-chat Schedule tool always records its creating session's mode; + // "" comes only from an out-of-band or legacy spec. Passing "" to + // CreateSessionWithProfile falls back to s.cfg.DefaultMode. Either way + // CreateSessionWithProfile admits the mode against the current ceiling, + // so a mode recorded under a looser deployment fails the fire. // This is the fire-time enforcement; the create seam (the schedule // manager) additionally rejects Mutating=false with a non-plan Mode at save time. mode := sched.Spec.Mode // "" means "use server's DefaultMode" diff --git a/internal/app/scheduler_fire_mode_test.go b/internal/app/scheduler_fire_mode_test.go new file mode 100644 index 0000000000..2f84d92556 --- /dev/null +++ b/internal/app/scheduler_fire_mode_test.go @@ -0,0 +1,131 @@ +package app + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "testing" + "time" + + "github.com/stacklok/mecatl/adapters/jsonlstore" + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/session" +) + +// scheduleModeFireTimeout bounds each fire so a fire that blocks on an +// unanswerable ask fails the test instead of hanging it. +const scheduleModeFireTimeout = 20 * time.Second + +// TestScheduledFireRunsInCreatingSessionMode is the regression for a mutating +// in-chat schedule that always recorded default mode: on a yolo server the +// fire then ran in default, its Write asked with no approver, and the fire +// hung until its deadline. A schedule created from a yolo session must fire in +// yolo and run its mutation without an ask. Once the same store is served by a +// deployment whose ceiling no longer admits yolo, the recorded mode is refused +// at fire-session admission: the fire fails fast and nothing runs. +func TestScheduledFireRunsInCreatingSessionMode(t *testing.T) { + ctx := context.Background() + workspace := t.TempDir() + storeDir := t.TempDir() + written := filepath.Join(workspace, "fired.txt") + writeCall := func(id session.ToolCallID, path string) mockllm.Turn { + args, err := json.Marshal(map[string]string{"path": path, "content": "fired\n"}) + if err != nil { + t.Fatal(err) + } + return mockllm.ToolCallTurn(session.NewToolCall(id, "Write", args)) + } + provider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("create", agent.ScheduleToolName, + json.RawMessage(`{"verb":"create","name":"writer","prompt":"write the file","cron":"@every 1h","mutating":true}`))), + mockllm.TextTurn("scheduled"), + writeCall("fire-write", written), + mockllm.TextTurn("fire done"), + ) + built, err := buildIsolated(t, ctx, Config{ + Workspace: workspace, StoreDir: storeDir, NoSoul: true, UseMock: true, MockProvider: provider, + Model: "main-model", PermissionMode: "yolo", PermissionModeFlagSet: true, + }) + if err != nil { + t.Fatalf("Build(yolo): %v", err) + } + creator, err := built.Service.CreateSession(ctx, session.ModeYolo, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession(yolo): %v", err) + } + run, err := built.Service.StartRun(ctx, creator.ID, "schedule a writer") + if err != nil { + t.Fatalf("StartRun: %v", err) + } + for ev := range run.Events() { + if ev.Type == session.EvToolResult && ev.ToolResult != nil && ev.ToolResult.IsError { + t.Fatalf("in-chat create failed: %q", ev.ToolResult.Content) + } + } + built.Service.FinishRun(creator.ID, run) + + jstore, err := jsonlstore.New(storeDir) + if err != nil { + t.Fatalf("jsonlstore.New: %v", err) + } + sched, err := jstore.ScheduleStore().Load(ctx, "writer") + if err != nil { + t.Fatalf("Load(writer): %v", err) + } + if sched.Spec.Mode != session.ModeYolo || !sched.Spec.Mutating { + t.Fatalf("recorded (mode %q, mutating %t), want (yolo, true): the creating session's mode", sched.Spec.Mode, sched.Spec.Mutating) + } + + fire, err := makeFireFunc(built.Service, jstore.ScheduleStore(), scheduleModeFireTimeout, nil)(ctx, sched, time.Now()) + if err != nil || fire.Stop != session.StopEndTurn { + t.Fatalf("yolo fire = (stop %q, err %v, %q), want end_turn", fire.Stop, err, fire.Err) + } + fired, err := built.Service.GetSession(ctx, fire.SessionID) + if err != nil { + t.Fatalf("GetSession(fire): %v", err) + } + if fired.Mode != session.ModeYolo { + t.Fatalf("fire session mode = %q, want yolo", fired.Mode) + } + if got, err := os.ReadFile(written); err != nil || string(got) != "fired\n" { + t.Fatalf("fire Write did not run unasked: content %q, err %v", got, err) + } + built.Close() + + // The same store under a deployment whose ceiling is accept-edits: the + // yolo-recorded schedule must be refused, not escalated or downgraded. + refusedPath := filepath.Join(workspace, "refused.txt") + tightProvider := mockllm.New(writeCall("refused-write", refusedPath), mockllm.TextTurn("should not run")) + tight, err := buildIsolated(t, ctx, Config{ + Workspace: workspace, StoreDir: storeDir, NoSoul: true, UseMock: true, MockProvider: tightProvider, + Model: "main-model", PermissionMode: "default", PermissionModeFlagSet: true, + }) + if err != nil { + t.Fatalf("Build(default): %v", err) + } + defer tight.Close() + tightStore, err := jsonlstore.New(storeDir) + if err != nil { + t.Fatalf("jsonlstore.New: %v", err) + } + sched, err = tightStore.ScheduleStore().Load(ctx, "writer") + if err != nil { + t.Fatalf("Load(writer) after relaunch: %v", err) + } + start := time.Now() + refused, err := makeFireFunc(tight.Service, tightStore.ScheduleStore(), scheduleModeFireTimeout, nil)(ctx, sched, time.Now()) + if err == nil || refused.Stop != session.StopError { + t.Fatalf("over-ceiling fire = (stop %q, err %v), want a refused fire", refused.Stop, err) + } + if elapsed := time.Since(start); elapsed >= scheduleModeFireTimeout { + t.Fatalf("over-ceiling fire took %s, want refused at admission, not at the deadline", elapsed) + } + if tightProvider.Calls() != 0 { + t.Fatalf("over-ceiling fire reached the model %d times, want 0", tightProvider.Calls()) + } + if _, err := os.Stat(refusedPath); !os.IsNotExist(err) { + t.Fatalf("over-ceiling fire wrote %s (stat err %v), want nothing run", refusedPath, err) + } +} diff --git a/user-docs/features/sessions/scheduled-tasks.md b/user-docs/features/sessions/scheduled-tasks.md index abebc36891..e3f5c8082d 100644 --- a/user-docs/features/sessions/scheduled-tasks.md +++ b/user-docs/features/sessions/scheduled-tasks.md @@ -57,6 +57,11 @@ It defaults to read-leaning behavior. A schedule that may use `Edit`, `Write`, or `Shell` must explicitly set `mutating: true`; this is not an implicit allow-all mode. +A mutating schedule created with the in-chat `Schedule` tool fires in the +permission mode its creating session had when it created the schedule. Every +fire checks that mode against the server ceiling again. If the server has since +restarted with a lower ceiling, the fire fails without running. + For an independently created schedule, the server selects placement from its configured default. The create request has no workspace field. Use the HTTP listener for this REST workflow: From aa5287a87e76de0e39fb71496dddb288d033af4c Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 18:11:43 +0300 Subject: [PATCH 45/48] fix(schedule): keep an unspecified schedule mode as the server default A gRPC or REST CreateSchedule/UpdateSchedule mapped an UNSPECIFIED mode to DEFAULT. On an allow-all server a mutating schedule created without a mode, which is what the mecatui overlay sends, then fired in default. Its writes asked with no approver and the fire hung, the same failure as the in-chat tool before 241042f51. The fire path already treats an empty mode as the server's DefaultMode, but nothing on the wire could produce one. protoToScheduleSpec now maps the mode with createModeFromProto, as CreateSession does, so UNSPECIFIED is stored as "". Each fire resolves it to the server's default session mode and admits it against the current ceiling. The read-back maps a stored "" to UNSPECIFIED so a GetSchedule then UpdateSchedule round trip keeps it unset instead of pinning DEFAULT. The create seam already validates "" as default, so a read-leaning schedule without PLAN is still refused, exactly as before. mecatui sends PLAN for a read-leaning create and UNSPECIFIED for a mutating one. The mapping lives on the schedule path only, and ModeFromString("") still means DEFAULT for its other callers. A read-leaning mecatui create was already refused on origin/main, since it sent DEFAULT. API compatibility: - Assessment: compatible semantic change, no major bump, no new feature identifier. Same shape as the approved CreateSession change in e68fb44d6: an UNSPECIFIED ScheduleSpec.mode now means the server's configured default session mode instead of DEFAULT. - Rationale: no field, enum, or RPC changes. On a server whose default session mode is default, behavior is identical: the fire resolves to default. Only servers started with a permission mode that defaults sessions elsewhere differ, and there the old behavior hung mutating fires headless. Clients that send an explicit mode are unaffected. - Read-back: a stored "" (new UNSPECIFIED creates, or embedder specs) now reads back as UNSPECIFIED instead of DEFAULT. Stored explicit modes, including every schedule created over the wire before this change, read back unchanged. A client that rendered UNSPECIFIED as default keeps working; Studio's mapper shows UNSPECIFIED as plan, as it already does for auto and yolo. - Stored data: no migration. Existing specs keep their explicit modes. - Upgrade: none required. To pin default on an allow-all server, send PERMISSION_MODE_DEFAULT explicitly. - Approval: the operator approved this change for the PR. Co-Authored-By: Claude Opus 5.5 --- cmd/mecatui/client/schedule.go | 20 ++- cmd/mecatui/client/schedule_test.go | 39 ++++++ cmd/mecatui/ui/schedule.go | 10 +- cmd/mecatui/ui/schedule_test.go | 56 +++++++- contracts/gen/go/mecatl/v1/schedule.pb.go | 4 + contracts/proto/mecatl/v1/schedule.proto | 4 + docs/architecture/api-surface.md | 5 +- internal/adapter/server/grpc_schedule.go | 10 +- internal/adapter/server/mapper.go | 20 ++- internal/app/scheduler_fire.go | 5 +- internal/app/scheduler_fire_mode_test.go | 124 ++++++++++++++++++ .../src/gen/mecatl/v1/schedule_pb.ts | 4 + .../features/sessions/scheduled-tasks.md | 13 +- user-docs/reference/grpc-schema.md | 2 +- 14 files changed, 291 insertions(+), 25 deletions(-) diff --git a/cmd/mecatui/client/schedule.go b/cmd/mecatui/client/schedule.go index 8cbc1e08b7..d367d8b3b7 100644 --- a/cmd/mecatui/client/schedule.go +++ b/cmd/mecatui/client/schedule.go @@ -492,16 +492,24 @@ func misfireToProtoFromString(s string) mecatlv1.MisfirePolicy { } } -// modeStringFromProto maps the proto PermissionMode enum to the canonical UI -// string, reusing ModeString (the harness-mode discipline). Unspecified defaults -// to "default". +// modeStringFromProto maps a schedule's proto PermissionMode to the canonical UI +// string, reusing ModeString (the harness-mode discipline). UNSPECIFIED maps to +// "": the schedule fires in the server's default session mode, which the client +// does not know, so it must not be shown as "default". func modeStringFromProto(m mecatlv1.PermissionMode) string { + if m == mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { + return "" + } return ModeString(m) } -// modeToProtoFromString maps a UI mode string to the proto enum, reusing -// ModeFromString. Unknown/empty maps to UNSPECIFIED (the server defaults that to -// DEFAULT). +// modeToProtoFromString maps a schedule's UI mode string to the proto enum. An +// empty mode goes out as UNSPECIFIED so the server's default session mode +// applies; it is deliberately not ModeFromString(""), which other callers rely +// on to mean DEFAULT. Any other value reuses ModeFromString. func modeToProtoFromString(s string) mecatlv1.PermissionMode { + if s == "" { + return mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED + } return ModeFromString(s) } diff --git a/cmd/mecatui/client/schedule_test.go b/cmd/mecatui/client/schedule_test.go index 8d31d79f2b..d542fafd99 100644 --- a/cmd/mecatui/client/schedule_test.go +++ b/cmd/mecatui/client/schedule_test.go @@ -420,3 +420,42 @@ func TestScheduleCmdsErrorMsgs(t *testing.T) { t.Fatalf("ListFiresCmd error msg = %+v", m) } } + +// TestScheduleModeUnsetMapsToUnspecified pins the schedule-only mode mapping. +// An unset mode goes out as UNSPECIFIED so the server's default session mode +// applies at fire (ModeFromString("") still means DEFAULT for other callers), +// and an UNSPECIFIED read-back stays unset instead of claiming "default". +func TestScheduleModeUnsetMapsToUnspecified(t *testing.T) { + for _, tc := range []struct { + mode string + want mecatlv1.PermissionMode + }{ + {mode: "", want: mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED}, + {mode: "plan", want: mecatlv1.PermissionMode_PERMISSION_MODE_PLAN}, + {mode: "default", want: mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT}, + } { + fake := &fakeScheduleClient{createResp: &mecatlv1.CreateScheduleResponse{Schedule: sampleProtoSchedule("m")}} + if _, err := newScheduleFakeClient(fake).CreateSchedule(context.Background(), ScheduleSpec{ + Name: "m", Prompt: "p", Trigger: ScheduleTrigger{Cron: "@every 1h"}, Mode: tc.mode, Mutating: true, + }); err != nil { + t.Fatalf("CreateSchedule(mode %q): %v", tc.mode, err) + } + if got := fake.lastCreate.GetSpec().GetMode(); got != tc.want { + t.Errorf("mode %q sent as %v, want %v", tc.mode, got, tc.want) + } + } + if ModeFromString("") != mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT { + t.Fatal(`ModeFromString("") must keep meaning DEFAULT for non-schedule callers`) + } + + unset := sampleProtoSchedule("u") + unset.Spec.Mode = mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED + fake := &fakeScheduleClient{getResp: &mecatlv1.GetScheduleResponse{Schedule: unset}} + s, err := newScheduleFakeClient(fake).GetSchedule(context.Background(), "u") + if err != nil { + t.Fatalf("GetSchedule: %v", err) + } + if s.Spec.Mode != "" { + t.Fatalf("UNSPECIFIED read back as %q, want empty (server default)", s.Spec.Mode) + } +} diff --git a/cmd/mecatui/ui/schedule.go b/cmd/mecatui/ui/schedule.go index b3a4342feb..0f15e63a0a 100644 --- a/cmd/mecatui/ui/schedule.go +++ b/cmd/mecatui/ui/schedule.go @@ -68,9 +68,10 @@ type scheduleState struct { // keeps it SIMPLE — name, prompt, trigger (cron OR NL), mutating. The trigger // field accepts EITHER a raw cron expression OR a natural-language phrase; on // submit, schedparse.Compile is tried first (compile to cron or one-shot), and -// only on no-match is the value treated verbatim as raw cron. Mode defaults to -// plan for non-mutating (the server enforces the mode↔mutating invariant); -// singleton defaults true. focusIdx is the cursor over the fields. +// only on no-match is the value treated verbatim as raw cron. The form has no +// mode field: a non-mutating schedule is sent as plan (the server requires it), +// and a mutating one leaves mode unset so its fires use the server's default +// session mode. Singleton defaults true. focusIdx is the cursor over the fields. type scheduleForm struct { name textinput.Model prompt textinput.Model @@ -384,6 +385,9 @@ func (m Model) submitScheduleCreate() (tea.Model, tea.Cmd, bool) { Singleton: true, Timezone: "UTC", } + if !f.mutating { + spec.Mode = "plan" + } // Return to the panel; the ScheduleMsg reducer appends the new row. m.schedule.view = schedulePanel m.schedule.form = scheduleForm{} diff --git a/cmd/mecatui/ui/schedule_test.go b/cmd/mecatui/ui/schedule_test.go index e392fc2a22..f89824de57 100644 --- a/cmd/mecatui/ui/schedule_test.go +++ b/cmd/mecatui/ui/schedule_test.go @@ -37,6 +37,7 @@ type fakeScheduleLister struct { lastFireName string lastFiresName string lastGetname string + lastCreateSpec client.ScheduleSpec } func (f *fakeScheduleLister) ListSchedules(_ context.Context) ([]client.Schedule, error) { @@ -56,8 +57,9 @@ func (f *fakeScheduleLister) GetSchedule(_ context.Context, name string) (client return f.sched, nil } -func (f *fakeScheduleLister) CreateSchedule(_ context.Context, _ client.ScheduleSpec) (client.Schedule, error) { +func (f *fakeScheduleLister) CreateSchedule(_ context.Context, spec client.ScheduleSpec) (client.Schedule, error) { f.createCalls++ + f.lastCreateSpec = spec if f.err != nil { return client.Schedule{}, f.err } @@ -1183,3 +1185,55 @@ func TestScheduleInspectRendersNeverFired(t *testing.T) { t.Errorf("never-fired inspect rendered \"in-flight\" (a never-claimed schedule must NOT render in-flight):\n%s", out) } } + +// TestScheduleCreateFormModeFollowsMutating pins the mode the create form +// sends. A read-leaning schedule must name plan, which the server requires; an +// empty mode there was refused. A mutating one leaves mode unset so its fires +// use the server's default session mode rather than an explicit default that +// asks with no approver on an allow-all server. +func TestScheduleCreateFormModeFollowsMutating(t *testing.T) { + for _, tc := range []struct { + toggle string + mutating bool + wantMode string + }{ + {toggle: "y", mutating: true, wantMode: ""}, + {toggle: "n", mutating: false, wantMode: "plan"}, + } { + t.Run("mutating="+tc.toggle, func(t *testing.T) { + fs := &fakeScheduleLister{sched: sampleSchedule("s")} + m := newScheduleModel(t, newScheduleConv(scheduleCaps()), fs, scheduleCaps()) + mm, _ := m.openSchedule() + m = applyAll(mm.(Model), client.SchedulesMsg{Schedules: nil}) + press := func(k tea.KeyPressMsg) tea.Cmd { + mm, cmd, _ := m.onScheduleKey(k) + m = mm.(Model) + return cmd + } + typeText := func(s string) { + for _, r := range s { + press(tea.KeyPressMsg{Code: r, Text: string(r)}) + } + } + tab := tea.KeyPressMsg{Code: tea.KeyTab, Text: "tab"} + press(tea.KeyPressMsg{Code: 'c', Text: "c"}) + typeText("s") + press(tab) + typeText("run it") + press(tab) + typeText("0 9 * * *") + press(tab) + press(tea.KeyPressMsg{Code: rune(tc.toggle[0]), Text: tc.toggle}) + cmd := press(tea.KeyPressMsg{Code: tea.KeyEnter}) + if cmd == nil { + t.Fatalf("submit returned no command (actionErr=%q)", m.schedule.actionErr) + } + m = feedCmd(t, m, cmd) + got := fs.lastCreateSpec + if fs.createCalls != 1 || got.Mutating != tc.mutating || got.Mode != tc.wantMode { + t.Fatalf("create sent (mutating %t, mode %q) in %d calls, want (mutating %t, mode %q) once", + got.Mutating, got.Mode, fs.createCalls, tc.mutating, tc.wantMode) + } + }) + } +} diff --git a/contracts/gen/go/mecatl/v1/schedule.pb.go b/contracts/gen/go/mecatl/v1/schedule.pb.go index f7d38ff3f0..399644fc82 100644 --- a/contracts/gen/go/mecatl/v1/schedule.pb.go +++ b/contracts/gen/go/mecatl/v1/schedule.pb.go @@ -260,6 +260,10 @@ type ScheduleSpec struct { Profile string `protobuf:"bytes,6,opt,name=profile,proto3" json:"profile,omitempty"` // mode is the session permission posture. Reuses the PermissionMode enum from // harness.proto (same package — proto allows cross-file refs within a package). + // A non-mutating schedule must use PLAN. For a mutating schedule, unspecified + // means each fire uses the server's configured default session mode at fire + // time; it reads back as unspecified. Every fire checks the mode against the + // server's mode ceiling and fails if the ceiling no longer allows it. Mode PermissionMode `protobuf:"varint,8,opt,name=mode,proto3,enum=mecatl.v1.PermissionMode" json:"mode,omitempty"` // limits are the bounded per-fire budgets. Reuses the Limits message from // harness.proto. They are PER-FIRE: each fire gets a fresh session with these diff --git a/contracts/proto/mecatl/v1/schedule.proto b/contracts/proto/mecatl/v1/schedule.proto index 952eeabe9b..0addddba50 100644 --- a/contracts/proto/mecatl/v1/schedule.proto +++ b/contracts/proto/mecatl/v1/schedule.proto @@ -160,6 +160,10 @@ message ScheduleSpec { reserved "workspace"; // mode is the session permission posture. Reuses the PermissionMode enum from // harness.proto (same package — proto allows cross-file refs within a package). + // A non-mutating schedule must use PLAN. For a mutating schedule, unspecified + // means each fire uses the server's configured default session mode at fire + // time; it reads back as unspecified. Every fire checks the mode against the + // server's mode ceiling and fails if the ceiling no longer allows it. PermissionMode mode = 8; // limits are the bounded per-fire budgets. Reuses the Limits message from // harness.proto. They are PER-FIRE: each fire gets a fresh session with these diff --git a/docs/architecture/api-surface.md b/docs/architecture/api-surface.md index 4e32ce6f2a..356ac66a61 100644 --- a/docs/architecture/api-surface.md +++ b/docs/architecture/api-surface.md @@ -198,7 +198,10 @@ entry; `engine/agent` knows nothing about it. explanation and no session id: no execution was admitted. It does not leave an uncertain pending owner blocking the next fresh slot. - Each fire creates a fresh `sched--` session owned by the schedule's captured owner, - with bounded limits. A schedule not marked mutating runs in plan mode. The fire + with bounded limits. A schedule not marked mutating runs in plan mode. A mutating + schedule runs in its recorded mode, or the server's default session mode when the + mode is unset (UNSPECIFIED on the wire); the fire's session creation admits that + mode against the current ceiling. The fire reattaches the exact placement persisted at creation, and fails before creating a session if that placement has drifted (`internal/app/scheduler_fire.go`). diff --git a/internal/adapter/server/grpc_schedule.go b/internal/adapter/server/grpc_schedule.go index 6a8d73cb28..4154925a75 100644 --- a/internal/adapter/server/grpc_schedule.go +++ b/internal/adapter/server/grpc_schedule.go @@ -187,7 +187,11 @@ func (h *ScheduleServer) ListFires(ctx context.Context, req *mecatlv1.ListFiresR // protoToScheduleSpec maps the proto ScheduleSpec to the port.ScheduleSpec the // Service methods take. It reuses the existing contentFromProto / limitsFromProto -// / modeFromProto mappers (the single content-validation path). TriggerSpec maps +// / createModeFromProto mappers (the single content-validation path). An +// UNSPECIFIED mode stays empty, as on CreateSession: a mutating schedule then +// fires in the server's configured default session mode, admitted at each fire, +// and a read-leaning one is still refused by the create seam unless it names +// plan. TriggerSpec maps // the cron string + one_shot Timestamp → time.Time. An absent trigger is a value // error (the create-seam's Trigger.Validate rejects it). Timestamps without a // created_at are left zero (the create-seam stamps CreatedAt itself, so a caller @@ -207,7 +211,7 @@ func protoToScheduleSpec(in *mecatlv1.ScheduleSpec) (port.ScheduleSpec, error) { Name: in.GetName(), Prompt: in.GetPrompt(), Profile: in.GetProfile(), - Mode: modeFromProto(in.GetMode()), + Mode: createModeFromProto(in.GetMode()), Limits: limitsFromProto(in.GetLimits()), Mutating: in.GetMutating(), MaxFires: int(in.GetMaxFires()), @@ -269,7 +273,7 @@ func scheduleSpecToProto(in port.ScheduleSpec) *mecatlv1.ScheduleSpec { Prompt: in.Prompt, Parts: contentToProto(in.Parts), Profile: in.Profile, - Mode: modeToProto(in.Mode), + Mode: scheduleModeToProto(in.Mode), Limits: limitsToProto(in.Limits), Mutating: in.Mutating, MaxFires: ClampInt32(in.MaxFires), diff --git a/internal/adapter/server/mapper.go b/internal/adapter/server/mapper.go index 53a16c1f05..8bec0bdb59 100644 --- a/internal/adapter/server/mapper.go +++ b/internal/adapter/server/mapper.go @@ -1413,10 +1413,11 @@ func modeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { } } -// createModeFromProto maps a CreateSession mode. Unlike modeFromProto, an -// UNSPECIFIED mode stays empty so Service.createSession applies the server's -// configured DefaultMode (the session half of the operator's permission mode), -// matching the HTTP create path. +// createModeFromProto maps a CreateSession or ScheduleSpec mode. Unlike +// modeFromProto, an UNSPECIFIED mode stays empty so Service.createSession +// applies the server's configured DefaultMode (the session half of the +// operator's permission mode), matching the HTTP create path. A schedule keeps +// the empty mode and resolves it the same way at each fire. func createModeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { if m == mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { return "" @@ -1424,6 +1425,17 @@ func createModeFromProto(m mecatlv1.PermissionMode) session.PermissionMode { return modeFromProto(m) } +// scheduleModeToProto reports a stored schedule mode. An empty mode means the +// fire uses the server's default session mode, so it reads back as UNSPECIFIED +// (round-tripping through createModeFromProto) rather than as an explicit +// DEFAULT that the fire may not use. +func scheduleModeToProto(m session.PermissionMode) mecatlv1.PermissionMode { + if m == "" { + return mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED + } + return modeToProto(m) +} + func guardrailApprovalKindFromProto(kind mecatlv1.GuardrailApprovalKind) session.GuardrailApprovalKind { switch kind { case mecatlv1.GuardrailApprovalKind_GUARDRAIL_APPROVAL_KIND_ACTION: diff --git a/internal/app/scheduler_fire.go b/internal/app/scheduler_fire.go index e6decccba2..2b26b2dd92 100644 --- a/internal/app/scheduler_fire.go +++ b/internal/app/scheduler_fire.go @@ -74,8 +74,9 @@ func makeFireFuncWithCancel(svc *server.Service, store port.ScheduleStore, defau // DefaultMode when unset, which reflects the operator's permission // configuration — for allow-all deployments this is ModeAuto or ModeYolo). // The in-chat Schedule tool always records its creating session's mode; - // "" comes only from an out-of-band or legacy spec. Passing "" to - // CreateSessionWithProfile falls back to s.cfg.DefaultMode. Either way + // "" comes from a gRPC/REST create that left mode UNSPECIFIED or from an + // embedder's spec. Passing "" to CreateSessionWithProfile falls back to + // s.cfg.DefaultMode. Either way // CreateSessionWithProfile admits the mode against the current ceiling, // so a mode recorded under a looser deployment fails the fire. // This is the fire-time enforcement; the create seam (the schedule diff --git a/internal/app/scheduler_fire_mode_test.go b/internal/app/scheduler_fire_mode_test.go index 2f84d92556..69f4828b30 100644 --- a/internal/app/scheduler_fire_mode_test.go +++ b/internal/app/scheduler_fire_mode_test.go @@ -3,15 +3,24 @@ package app import ( "context" "encoding/json" + "net" "os" "path/filepath" "testing" "time" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" + "google.golang.org/grpc/test/bufconn" + "github.com/stacklok/mecatl/adapters/jsonlstore" + mecatlv1 "github.com/stacklok/mecatl/contracts/gen/go/mecatl/v1" "github.com/stacklok/mecatl/engine/adapter/mockllm" "github.com/stacklok/mecatl/engine/agent" "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/server" ) // scheduleModeFireTimeout bounds each fire so a fire that blocks on an @@ -129,3 +138,118 @@ func TestScheduledFireRunsInCreatingSessionMode(t *testing.T) { t.Fatalf("over-ceiling fire wrote %s (stat err %v), want nothing run", refusedPath, err) } } + +// dialScheduleService serves the real ScheduleService handler for built over an +// in-memory listener, so a test drives the wire mapping a remote client uses. +func dialScheduleService(t *testing.T, built *Built) mecatlv1.ScheduleServiceClient { + t.Helper() + lis := bufconn.Listen(1 << 20) + gs := grpc.NewServer() + mecatlv1.RegisterScheduleServiceServer(gs, server.NewScheduleServer(built.Service)) + go func() { _ = gs.Serve(lis) }() + conn, err := grpc.NewClient("passthrough:///bufnet", + grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { return lis.DialContext(ctx) }), + grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + t.Fatalf("dial: %v", err) + } + t.Cleanup(func() { + _ = conn.Close() + gs.Stop() + _ = lis.Close() + }) + return mecatlv1.NewScheduleServiceClient(conn) +} + +// TestGRPCScheduleUnspecifiedModeUsesServerDefault pins the wire half of the +// same hang: a gRPC CreateSchedule that left mode UNSPECIFIED was stored as +// default, so on a yolo server its fire asked with no approver. UNSPECIFIED +// now stays unset, reads back as UNSPECIFIED, and the fire runs in the +// server's default session mode. An explicit DEFAULT is still stored and read +// back as default, and a read-leaning schedule still has to name PLAN. +func TestGRPCScheduleUnspecifiedModeUsesServerDefault(t *testing.T) { + ctx := context.Background() + workspace := t.TempDir() + storeDir := t.TempDir() + written := filepath.Join(workspace, "wire-fired.txt") + args, err := json.Marshal(map[string]string{"path": written, "content": "fired\n"}) + if err != nil { + t.Fatal(err) + } + provider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("fire-write", "Write", args)), + mockllm.TextTurn("fire done"), + ) + built, err := buildIsolated(t, ctx, Config{ + Workspace: workspace, StoreDir: storeDir, NoSoul: true, UseMock: true, MockProvider: provider, + Model: "main-model", PermissionMode: "yolo", PermissionModeFlagSet: true, + }) + if err != nil { + t.Fatalf("Build(yolo): %v", err) + } + defer built.Close() + client := dialScheduleService(t, built) + spec := func(name string, mutating bool, mode mecatlv1.PermissionMode) *mecatlv1.ScheduleSpec { + return &mecatlv1.ScheduleSpec{ + Name: name, Prompt: "write the file", Mutating: mutating, Mode: mode, + Trigger: &mecatlv1.TriggerSpec{Cron: "@every 1h"}, + } + } + + unset, err := client.CreateSchedule(ctx, &mecatlv1.CreateScheduleRequest{Spec: spec("unset", true, mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED)}) + if err != nil { + t.Fatalf("CreateSchedule(unset): %v", err) + } + if got := unset.GetSchedule().GetSpec().GetMode(); got != mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { + t.Fatalf("unset create read back mode %s, want UNSPECIFIED", got) + } + explicit, err := client.CreateSchedule(ctx, &mecatlv1.CreateScheduleRequest{Spec: spec("explicit", true, mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT)}) + if err != nil { + t.Fatalf("CreateSchedule(explicit): %v", err) + } + if got := explicit.GetSchedule().GetSpec().GetMode(); got != mecatlv1.PermissionMode_PERMISSION_MODE_DEFAULT { + t.Fatalf("explicit create read back mode %s, want DEFAULT", got) + } + _, err = client.CreateSchedule(ctx, &mecatlv1.CreateScheduleRequest{Spec: spec("ro-unset", false, mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED)}) + if status.Code(err) != codes.InvalidArgument { + t.Fatalf("read-leaning UNSPECIFIED create = %v, want InvalidArgument (a read-leaning schedule must name plan)", err) + } + if _, err := client.CreateSchedule(ctx, &mecatlv1.CreateScheduleRequest{Spec: spec("ro-plan", false, mecatlv1.PermissionMode_PERMISSION_MODE_PLAN)}); err != nil { + t.Fatalf("read-leaning PLAN create: %v", err) + } + + jstore, err := jsonlstore.New(storeDir) + if err != nil { + t.Fatalf("jsonlstore.New: %v", err) + } + stored, err := jstore.ScheduleStore().Load(ctx, "explicit") + if err != nil || stored.Spec.Mode != session.ModeDefault { + t.Fatalf("explicit stored mode = %q (err %v), want default", stored.Spec.Mode, err) + } + sched, err := jstore.ScheduleStore().Load(ctx, "unset") + if err != nil { + t.Fatalf("Load(unset): %v", err) + } + if sched.Spec.Mode != "" { + t.Fatalf("unset stored mode = %q, want empty (the server default at fire)", sched.Spec.Mode) + } + if got, err := client.GetSchedule(ctx, &mecatlv1.GetScheduleRequest{Name: "unset"}); err != nil || + got.GetSchedule().GetSpec().GetMode() != mecatlv1.PermissionMode_PERMISSION_MODE_UNSPECIFIED { + t.Fatalf("GetSchedule(unset) = (%v, %v), want mode UNSPECIFIED", got.GetSchedule().GetSpec().GetMode(), err) + } + + fire, err := makeFireFunc(built.Service, jstore.ScheduleStore(), scheduleModeFireTimeout, nil)(ctx, sched, time.Now()) + if err != nil || fire.Stop != session.StopEndTurn { + t.Fatalf("unset-mode fire = (stop %q, err %v, %q), want end_turn", fire.Stop, err, fire.Err) + } + fired, err := built.Service.GetSession(ctx, fire.SessionID) + if err != nil { + t.Fatalf("GetSession(fire): %v", err) + } + if fired.Mode != session.ModeYolo { + t.Fatalf("fire session mode = %q, want the server default yolo", fired.Mode) + } + if got, err := os.ReadFile(written); err != nil || string(got) != "fired\n" { + t.Fatalf("fire Write did not run unasked: content %q, err %v", got, err) + } +} diff --git a/sdk/typescript/src/gen/mecatl/v1/schedule_pb.ts b/sdk/typescript/src/gen/mecatl/v1/schedule_pb.ts index 0e3aa38c84..65b2a8a27b 100644 --- a/sdk/typescript/src/gen/mecatl/v1/schedule_pb.ts +++ b/sdk/typescript/src/gen/mecatl/v1/schedule_pb.ts @@ -176,6 +176,10 @@ export type ScheduleSpec = Message<"mecatl.v1.ScheduleSpec"> & { /** * mode is the session permission posture. Reuses the PermissionMode enum from * harness.proto (same package — proto allows cross-file refs within a package). + * A non-mutating schedule must use PLAN. For a mutating schedule, unspecified + * means each fire uses the server's configured default session mode at fire + * time; it reads back as unspecified. Every fire checks the mode against the + * server's mode ceiling and fails if the ceiling no longer allows it. * * @generated from field: mecatl.v1.PermissionMode mode = 8; */ diff --git a/user-docs/features/sessions/scheduled-tasks.md b/user-docs/features/sessions/scheduled-tasks.md index e3f5c8082d..f9369041b6 100644 --- a/user-docs/features/sessions/scheduled-tasks.md +++ b/user-docs/features/sessions/scheduled-tasks.md @@ -57,10 +57,15 @@ It defaults to read-leaning behavior. A schedule that may use `Edit`, `Write`, or `Shell` must explicitly set `mutating: true`; this is not an implicit allow-all mode. -A mutating schedule created with the in-chat `Schedule` tool fires in the -permission mode its creating session had when it created the schedule. Every -fire checks that mode against the server ceiling again. If the server has since -restarted with a lower ceiling, the fire fails without running. +A read-leaning schedule must set `mode` to plan. For a mutating schedule, the +fire's permission mode depends on how you created it: + +- The in-chat `Schedule` tool records the mode its creating session had. +- A gRPC or REST request uses its `mode` field. When `mode` is unspecified, as + in the `mecatui` overlay, each fire uses the server's default session mode. + +Every fire checks its mode against the server ceiling again. If the server has +since restarted with a lower ceiling, the fire fails without running. For an independently created schedule, the server selects placement from its configured default. The create request has no workspace field. Use the HTTP diff --git a/user-docs/reference/grpc-schema.md b/user-docs/reference/grpc-schema.md index f787a154f5..fcd91d4cbf 100644 --- a/user-docs/reference/grpc-schema.md +++ b/user-docs/reference/grpc-schema.md @@ -4444,7 +4444,7 @@ ScheduleState; the two halves together form a Schedule. | `trigger` | `TriggerSpec` | | | trigger is the firing trigger (cron XOR one_shot). | | `selector` | `ScheduleProviderSelector` | | | selector selects the provider+model the fires run on. A zero value means the deployment default. | | `profile` | `string` | | | profile is the session tool-surface profile ("" default, "no-fs" file-less). | -| `mode` | `PermissionMode` | | | mode is the session permission posture. Reuses the PermissionMode enum from harness.proto (same package — proto allows cross-file refs within a package). | +| `mode` | `PermissionMode` | | | mode is the session permission posture. Reuses the PermissionMode enum from harness.proto (same package — proto allows cross-file refs within a package). A non-mutating schedule must use PLAN. For a mutating schedule, unspecified means each fire uses the server's configured default session mode at fire time; it reads back as unspecified. Every fire checks the mode against the server's mode ceiling and fails if the ceiling no longer allows it. | | `limits` | `Limits` | | | limits are the bounded per-fire budgets. Reuses the Limits message from harness.proto. They are PER-FIRE: each fire gets a fresh session with these limits. | | `mutating` | `bool` | | | mutating is the explicit write opt-in. The DEFAULT is false (read-leaning), the same conservative default as a subagent. | | `max_fires` | `int32` | | | max_fires bounds the TOTAL number of fires for a cron schedule (0 = forever). Cron-only: a one-shot fires once by definition and max_fires is ignored. | From e8c04bb33b117c8c80a5e52bff7b4a3078ed4647 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Fri, 16 Oct 2026 18:19:59 +0300 Subject: [PATCH 46/48] fix(studio): show and preserve auto, yolo, and server-default schedule modes Studio mapped every schedule mode other than default and acceptEdits to plan. A schedule created in chat now records its creator's mode (auto or yolo), and a wire create with no mode stores the server default, so those schedules were shown as plan. Worse, editing one from Studio sent plan back while it stayed mutating, so its next fire ran in plan and could not write. Schedule responses now report the actual mode, including auto, yolo, and serverDefault, with honest labels in the detail view. Create requests keep the three modes Studio can choose. The update request's mode is optional: when the form keeps a mode Studio cannot set, it omits it and the stored mode is preserved unchanged instead of being coerced to plan. Co-Authored-By: Claude Opus 5.5 --- apps/contracts/openapi.json | 18 +++++--- apps/contracts/src/generated/types.gen.ts | 6 +-- apps/contracts/src/schemas/schedules.ts | 26 +++++++++++- apps/server/src/mecatl/schedules.test.ts | 41 ++++++++++++++++++ apps/server/src/mecatl/schedules.ts | 21 +++++++++- .../features/schedules/schedule-detail.tsx | 19 ++++++--- .../schedules/schedule-form-value.test.ts | 29 +++++++++++++ .../features/schedules/schedule-form-value.ts | 42 +++++++++++++++++-- .../src/features/schedules/schedule-form.tsx | 21 +++++++--- 9 files changed, 197 insertions(+), 26 deletions(-) diff --git a/apps/contracts/openapi.json b/apps/contracts/openapi.json index 58e5450684..c306b5858c 100644 --- a/apps/contracts/openapi.json +++ b/apps/contracts/openapi.json @@ -5531,7 +5531,10 @@ "enum": [ "default", "plan", - "acceptEdits" + "acceptEdits", + "auto", + "yolo", + "serverDefault" ] }, "modelId": { @@ -5886,7 +5889,10 @@ "enum": [ "default", "plan", - "acceptEdits" + "acceptEdits", + "auto", + "yolo", + "serverDefault" ] }, "modelId": { @@ -6194,8 +6200,7 @@ "default", "plan", "acceptEdits" - ], - "default": "plan" + ] }, "mutating": { "type": "boolean", @@ -6310,7 +6315,10 @@ "enum": [ "default", "plan", - "acceptEdits" + "acceptEdits", + "auto", + "yolo", + "serverDefault" ] }, "modelId": { diff --git a/apps/contracts/src/generated/types.gen.ts b/apps/contracts/src/generated/types.gen.ts index 01c7927f99..9f9d942d8e 100644 --- a/apps/contracts/src/generated/types.gen.ts +++ b/apps/contracts/src/generated/types.gen.ts @@ -1854,7 +1854,7 @@ export type ListSchedulesResponses = { lastFireAt: string; lastFireSessionId: string; maxFires: number; - mode: 'default' | 'plan' | 'acceptEdits'; + mode: 'default' | 'plan' | 'acceptEdits' | 'auto' | 'yolo' | 'serverDefault'; modelId: string; mutating: boolean; name: string; @@ -1965,7 +1965,7 @@ export type CreateScheduleResponses = { lastFireAt: string; lastFireSessionId: string; maxFires: number; - mode: 'default' | 'plan' | 'acceptEdits'; + mode: 'default' | 'plan' | 'acceptEdits' | 'auto' | 'yolo' | 'serverDefault'; modelId: string; mutating: boolean; name: string; @@ -2141,7 +2141,7 @@ export type UpdateScheduleResponses = { lastFireAt: string; lastFireSessionId: string; maxFires: number; - mode: 'default' | 'plan' | 'acceptEdits'; + mode: 'default' | 'plan' | 'acceptEdits' | 'auto' | 'yolo' | 'serverDefault'; modelId: string; mutating: boolean; name: string; diff --git a/apps/contracts/src/schemas/schedules.ts b/apps/contracts/src/schemas/schedules.ts index 255e82bea3..b430851d73 100644 --- a/apps/contracts/src/schemas/schedules.ts +++ b/apps/contracts/src/schemas/schedules.ts @@ -12,6 +12,21 @@ export const maximumInt32 = 2_147_483_647; export const scheduleModeSchema = z.enum(["default", "plan", "acceptEdits"]); +/** + * A schedule's reported mode. It adds what a schedule created outside Studio + * can run in: `auto` and `yolo` (an in-chat schedule records its creating + * session's mode), and `serverDefault` (no mode was set, so each fire uses the + * server's default session mode). Studio reads these but never requests them. + */ +export const scheduleReportedModeSchema = z.enum([ + "default", + "plan", + "acceptEdits", + "auto", + "yolo", + "serverDefault", +]); + /** Each segment of an IANA zone name starts with an uppercase letter. */ const ianaZoneName = /^[A-Z][A-Za-z0-9_+-]*(?:\/[A-Z][A-Za-z0-9_+-]*)*$/u; @@ -72,7 +87,14 @@ export const createScheduleRequestSchema = scheduleWriteSchema.extend({ name: z.string().trim().min(1).max(160), }); -export const updateScheduleRequestSchema = scheduleWriteSchema; +/** + * An update may omit `mode` to keep the stored one, which is how a writing + * schedule whose mode Studio cannot set (`auto`, `yolo`, `serverDefault`) is + * edited without changing it. A sent mode is still one Studio can create. + */ +export const updateScheduleRequestSchema = scheduleWriteSchema.extend({ + mode: scheduleModeSchema.optional(), +}); export const scheduleSchema = z.object({ enabled: z.boolean(), @@ -80,7 +102,7 @@ export const scheduleSchema = z.object({ lastFireAt: z.string().nullable(), lastFireSessionId: z.string(), maxFires: z.number().int().nonnegative(), - mode: scheduleModeSchema, + mode: scheduleReportedModeSchema, modelId: z.string(), mutating: z.boolean(), name: z.string(), diff --git a/apps/server/src/mecatl/schedules.test.ts b/apps/server/src/mecatl/schedules.test.ts index e0d081504d..ad154af202 100644 --- a/apps/server/src/mecatl/schedules.test.ts +++ b/apps/server/src/mecatl/schedules.test.ts @@ -243,6 +243,47 @@ describe("Mecatl schedule spec mapping", () => { expect([a.mode, b.mode, c.mode]).toEqual(["default", "acceptEdits", "plan"]); }); + it("reports modes set outside Studio instead of folding them into plan", async () => { + // An in-chat schedule records its creator's mode (auto or yolo), and one + // created without a mode fires in the server's default session mode. + for (const [mode, want] of [ + [PermissionMode.AUTO, "auto"], + [PermissionMode.YOLO, "yolo"], + [PermissionMode.UNSPECIFIED, "serverDefault"], + ] as const) { + const list = vi.fn().mockResolvedValue({ + schedules: [spec({ mode, mutating: true }).schedule], + }); + const service = createMecatlScheduleService( + { schedules: { list } } as unknown as Client, + true, + ); + + const response = await service.list(); + expect(response.items[0]?.mode, String(mode)).toBe(want); + } + }); + + it("keeps the stored mode when an update omits it, and plan when writes are off", async () => { + for (const stored of [PermissionMode.AUTO, PermissionMode.YOLO, PermissionMode.UNSPECIFIED]) { + const current = spec({ mode: stored, mutating: true, timezone: "Europe/Rome" }); + const get = vi.fn().mockResolvedValue(current); + const update = vi.fn().mockResolvedValue(current); + const service = createMecatlScheduleService( + { schedules: { get, update } } as unknown as Client, + true, + ); + + await service.update("s", { ...baseWriteRequest(), mode: undefined, mutating: true }); + await service.update("s", { ...baseWriteRequest(), mode: undefined, mutating: false }); + await service.update("s", { ...baseWriteRequest(), mode: "acceptEdits", mutating: true }); + expect( + update.mock.calls.map((call) => call[0].spec.mode), + String(stored), + ).toEqual([stored, PermissionMode.PLAN, PermissionMode.ACCEPT_EDITS]); + } + }); + it("derives schedule status from enabled, in-flight, and pending claims", async () => { const rows = [ { name: "paused", state: { enabled: false } }, diff --git a/apps/server/src/mecatl/schedules.ts b/apps/server/src/mecatl/schedules.ts index 0fbe5601bd..09b7debecf 100644 --- a/apps/server/src/mecatl/schedules.ts +++ b/apps/server/src/mecatl/schedules.ts @@ -148,7 +148,7 @@ function toSdkSpec( }, maxFires: cron ? request.maxFires : 0, misfire: current?.misfire ?? 0, - mode: modeToSdk(request.mode), + mode: writeModeToSdk(request, current), mutating: request.mutating, name, oneShotMaxRetries: once && request.oneShotRetry ? request.oneShotMaxRetries : 0, @@ -282,10 +282,27 @@ function modeToSdk(mode: UpdateScheduleRequest["mode"]): PermissionMode { return PermissionMode.PLAN; } +/** + * The mode an update sends. An omitted mode on a writing schedule keeps the + * stored one verbatim, including an unspecified mode (the server default) and + * the autonomous modes Studio cannot request; a read-only schedule is plan. + */ +function writeModeToSdk(request: UpdateScheduleRequest, current?: ScheduleSpec): PermissionMode { + if (request.mode !== undefined) return modeToSdk(request.mode); + if (!request.mutating) return PermissionMode.PLAN; + return current?.mode ?? PermissionMode.PLAN; +} + +// Auto, yolo, and an unspecified mode are reported as such, not folded into +// plan: an in-chat schedule records its creator's mode, and a schedule created +// without a mode fires in the server's default session mode. function modeFromSdk(mode: PermissionMode): ScheduleResponse["mode"] { + if (mode === PermissionMode.PLAN) return "plan"; if (mode === PermissionMode.DEFAULT) return "default"; if (mode === PermissionMode.ACCEPT_EDITS) return "acceptEdits"; - return "plan"; + if (mode === PermissionMode.AUTO) return "auto"; + if (mode === PermissionMode.YOLO) return "yolo"; + return "serverDefault"; } function profileToSdk(profile: UpdateScheduleRequest["profile"]): string { diff --git a/apps/web/src/features/schedules/schedule-detail.tsx b/apps/web/src/features/schedules/schedule-detail.tsx index d5d8cac68b..c3bd01dc90 100644 --- a/apps/web/src/features/schedules/schedule-detail.tsx +++ b/apps/web/src/features/schedules/schedule-detail.tsx @@ -61,6 +61,7 @@ import { useShortcutSuppression } from "../shortcuts/shortcut-provider"; import { describeCron } from "./describe-cron"; import { RunTime } from "./run-time"; import { canEditSchedule, ScheduleForm, toastScheduleSaved } from "./schedule-form"; +import { scheduleModeLabel } from "./schedule-form-value"; import { ScheduleStatusBadge } from "./schedule-status"; type Schedule = ListSchedulesResponse["items"][number]; @@ -254,7 +255,17 @@ export function ScheduleDetail({ scheduleName }: { scheduleName: string }) {
- {modeLabel(schedule.mode)} + + {scheduleModeLabel(schedule.mode)} + {schedule.mutating && writes enabled} {schedule.profile === "noFilesystem" && no filesystem}
@@ -272,7 +283,7 @@ export function ScheduleDetail({ scheduleName }: { scheduleName: string }) {
- + ); } - -function modeLabel(mode: Schedule["mode"]) { - return mode === "acceptEdits" ? "Accept edits" : mode === "plan" ? "Plan" : "Default"; -} diff --git a/apps/web/src/features/schedules/schedule-form-value.test.ts b/apps/web/src/features/schedules/schedule-form-value.test.ts index 70ca3205a9..77a8664526 100644 --- a/apps/web/src/features/schedules/schedule-form-value.test.ts +++ b/apps/web/src/features/schedules/schedule-form-value.test.ts @@ -12,6 +12,7 @@ import { phraseTriggerPatch, type Schedule, scheduleFormProblem, + scheduleModeLabel, TRIGGER_FIELDS, type TriggerPatch, triggerFromValue, @@ -61,6 +62,34 @@ describe("schedule form value mapping", () => { } }); + it("keeps a mode set outside Studio by omitting it, and plan when writes go off", () => { + // Studio cannot send auto, yolo, or the server default; an edit must not + // replace them with a mode it can. + for (const mode of ["auto", "yolo", "serverDefault"] as const) { + const existing = schedule({ mode, mutating: true }); + const value = valueFromSchedule(existing); + expect(bodyFromValue(value, existing), mode).toMatchObject({ + mode: undefined, + mutating: true, + }); + expect(bodyFromValue({ ...value, allowWrites: false }, existing), mode).toMatchObject({ + mode: "plan", + mutating: false, + }); + expect(bodyFromValue({ ...value, writeMode: "acceptEdits" }, existing), mode).toMatchObject({ + mode: "acceptEdits", + mutating: true, + }); + } + }); + + it("labels the modes set outside Studio honestly", () => { + expect(scheduleModeLabel("auto")).toBe("Auto (set outside Studio)"); + expect(scheduleModeLabel("yolo")).toBe("YOLO (set outside Studio)"); + expect(scheduleModeLabel("serverDefault")).toBe("Server default"); + expect(scheduleModeLabel("default")).toBe("Default"); + }); + it("sends an existing schedule's trigger exactly as stored", () => { for (const trigger of [ { expression: "0 9 * * *", kind: "cron", timezone: "" }, diff --git a/apps/web/src/features/schedules/schedule-form-value.ts b/apps/web/src/features/schedules/schedule-form-value.ts index a9e85efd49..126dab5256 100644 --- a/apps/web/src/features/schedules/schedule-form-value.ts +++ b/apps/web/src/features/schedules/schedule-form-value.ts @@ -11,6 +11,35 @@ import { export type Schedule = ListSchedulesResponse["items"][number]; export type ScheduleBody = CreateScheduleData["body"]; +/** A mode Studio can send: `scheduleModeSchema` in `contracts/src/schemas/schedules.ts`. */ +export type RequestableScheduleMode = NonNullable; + +/** + * Whether Studio can send this mode. `auto` and `yolo` (recorded by an in-chat + * schedule) and `serverDefault` (no mode set) come from outside Studio; an + * edit keeps them by omitting the mode rather than replacing them. + */ +export function isRequestableScheduleMode(mode: Schedule["mode"]): mode is RequestableScheduleMode { + return mode === "default" || mode === "plan" || mode === "acceptEdits"; +} + +/** The label for a schedule's mode, naming the ones set outside Studio as such. */ +export function scheduleModeLabel(mode: Schedule["mode"]): string { + switch (mode) { + case "acceptEdits": + return "Accept edits"; + case "plan": + return "Plan"; + case "auto": + return "Auto (set outside Studio)"; + case "yolo": + return "YOLO (set outside Studio)"; + case "serverDefault": + return "Server default"; + default: + return "Default"; + } +} export interface FormValue { allowWrites: boolean; @@ -35,8 +64,9 @@ export interface FormValue { timezone: string; triggerKind: "cron" | "once"; /** - * The permission mode a writing schedule runs in. `plan` is only ever - * loaded from a stored writing schedule, so saving it unchanged keeps it. + * The permission mode a writing schedule runs in. `plan` and the modes set + * outside Studio are only ever loaded from a stored writing schedule, so + * saving it unchanged keeps them. */ writeMode: Schedule["mode"]; } @@ -139,7 +169,13 @@ export function bodyFromValue(value: FormValue, schedule?: Schedule): ScheduleBo const trigger = triggerFromValue(value, schedule); return { maxFires: Math.max(0, Number(value.maxFires) || 0), - mode: value.allowWrites ? value.writeMode : "plan", + // A mode Studio cannot send is kept by omitting it (the BFF keeps the + // stored mode), never replaced with one Studio can. + mode: !value.allowWrites + ? "plan" + : isRequestableScheduleMode(value.writeMode) + ? value.writeMode + : undefined, mutating: value.allowWrites, name: value.name.trim(), oneShotMaxRetries: value.oneShotRetry ? Math.max(0, Number(value.oneShotMaxRetries) || 0) : 0, diff --git a/apps/web/src/features/schedules/schedule-form.tsx b/apps/web/src/features/schedules/schedule-form.tsx index 336fecd1ef..ca3d3580f9 100644 --- a/apps/web/src/features/schedules/schedule-form.tsx +++ b/apps/web/src/features/schedules/schedule-form.tsx @@ -57,6 +57,18 @@ const TRIGGER_LOCKED_NOTE = const NO_PHRASE: PhraseOutcome = { kind: "none" }; +/** + * The write-mode options offered only to keep a stored writing schedule's mode + * as it is: modes Studio never offers for a new schedule. Accept edits and + * default are always offered, so they have no entry here. + */ +const KEPT_MODE_OPTIONS: Partial> = { + auto: "Keep Auto, set outside Studio", + plan: "Plan only, changes are refused", + serverDefault: "Keep the server's default mode", + yolo: "Keep YOLO, set outside Studio", +}; + const PHRASE_PLACEHOLDER = "every 30 minutes · daily at 9am · next monday 3pm · in 2 hours"; const PHRASE_HINT = 'Not recognised — try "every weekday at 9am" or a cron expression'; @@ -157,8 +169,9 @@ export function ScheduleForm({ } } - // `plan` is offered only to keep a stored writing schedule's mode as it is. - const offerPlanMode = schedule?.mutating === true && schedule.mode === "plan"; + // `plan` and the modes set outside Studio are offered only to keep a stored + // writing schedule's mode as it is. + const keptMode = schedule?.mutating === true ? KEPT_MODE_OPTIONS[schedule.mode] : undefined; const phrasePreview = describePhraseOutcome(phraseOutcome); const phraseNote = phrasePreview ?? (phrase.trim() ? PHRASE_HINT : null); // Formatted from the very trigger that will be sent, never from the inputs. @@ -328,9 +341,7 @@ export function ScheduleForm({ options={[ { label: "Accept edits automatically", value: "acceptEdits" }, { label: "Ask when approval is needed", value: "default" }, - ...(offerPlanMode - ? [{ label: "Plan only, changes are refused", value: "plan" }] - : []), + ...(keptMode && schedule ? [{ label: keptMode, value: schedule.mode }] : []), ]} value={value.writeMode} /> From 71bdd3b029d2a7548547a5ed75cf8b0dc5f6d426 Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Mon, 19 Oct 2026 12:30:06 +0300 Subject: [PATCH 47/48] perf(agent): stamp the session mode only for tools that read it dea760962 stamped the executing session's mode on every tool call's context in timeExecute. That costs two allocations per call (the context node and the boxed mode string), and the Perf gate flagged BenchmarkRunReadParallelTurn and BenchmarkSteadyStateReadParallelTurn at +8 allocs/op (+4%), above its epsilon. The only reader is the Schedule tool's mutating create. An unexported sessionModeReader marker now gates the stamp. ScheduleTool and its plan-aware wrapper carry it, so every other tool call is back to its main allocation count. TestScheduledFireRunsInCreatingSessionMode and TestScheduleTool_MutatingCreateRecordsCreatingSessionMode both fail if the marker is dropped. Co-Authored-By: Claude Opus 5.5 --- engine/agent/dispatch.go | 2 +- engine/agent/scheduletool.go | 8 ++++++++ engine/agent/sessionorigin.go | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/engine/agent/dispatch.go b/engine/agent/dispatch.go index 5ffad3848d..81371f7a1d 100644 --- a/engine/agent/dispatch.go +++ b/engine/agent/dispatch.go @@ -2058,7 +2058,7 @@ func (e *Engine) timeExecute(ctx context.Context, r *Run, sess *session.Session, ev.Turn = turnIdx r.children.safeEmit(ev) } - if sess != nil { + if _, reads := t.(sessionModeReader); reads && sess != nil { // Read at execution, like parentCaps' parentMode, so a schedule created // after a mid-session mode change records the mode it was created under. ctx = withSessionMode(ctx, sess.Mode) diff --git a/engine/agent/scheduletool.go b/engine/agent/scheduletool.go index bfbcb66265..f793c02a58 100644 --- a/engine/agent/scheduletool.go +++ b/engine/agent/scheduletool.go @@ -137,6 +137,10 @@ type ScheduleTool struct { mgr port.ScheduleManager } +// readsSessionMode marks the tool as a sessionModeReader: a mutating create +// records the executing session's mode. +func (*ScheduleTool) readsSessionMode() {} + // NewScheduleTool constructs the mutating Schedule tool over the injected // port.ScheduleManager. mgr must be non-nil; NewScheduleTool panics otherwise // (a composition-root programming error — the tool has nothing to drive without @@ -271,6 +275,10 @@ type planAwareScheduleTool struct { // the SCHEMA would make the model guess why its create was refused). func (t *planAwareScheduleTool) Spec() tool.ToolSpec { return t.base.Spec() } +// readsSessionMode forwards the base's sessionModeReader marker, so a create +// passed through to the base still sees the executing session's mode. +func (*planAwareScheduleTool) readsSessionMode() {} + // ReadOnly reports true so the plan-mode catalog projection advertises the tool // (see NewPlanAwareScheduleTool for the soundness argument). func (*planAwareScheduleTool) ReadOnly() bool { return true } diff --git a/engine/agent/sessionorigin.go b/engine/agent/sessionorigin.go index 143ae3dbb8..edfb89cc73 100644 --- a/engine/agent/sessionorigin.go +++ b/engine/agent/sessionorigin.go @@ -40,11 +40,21 @@ func sessionOriginFromContext(ctx context.Context) session.SessionID { type sessionModeContextKey struct{} +// sessionModeReader marks a tool whose Execute reads sessionModeFromContext. +// timeExecute stamps the mode only for these tools, so the per-call context +// node and the boxed mode stay off every other tool call's hot path. A wrapper +// that forwards to such a tool (planAwareScheduleTool) must carry the marker +// too, or the wrapped call sees the empty mode. +type sessionModeReader interface { + readsSessionMode() +} + // withSessionMode returns a child context carrying the executing session's // permission mode at the moment a tool call executes. Its one writer is // timeExecute, which stamps sess.Mode per call (not once per run) because the -// mode can change between dispatches; its one reader is ScheduleTool.create, -// which records it as a mutating schedule's fire mode. Unexported for the same +// mode can change between dispatches, and only for a sessionModeReader; its one +// reader is ScheduleTool.create, which records it as a mutating schedule's fire +// mode. Unexported for the same // reason as withSessionOrigin: the mode must come from the run, never from an // embedder or from model arguments, or a schedule could name a mode its // creating session never held. From 904efea69005c987e8729add9a3b413b681305bf Mon Sep 17 00:00:00 2001 From: Alejandro Ponce Date: Mon, 19 Oct 2026 12:51:00 +0300 Subject: [PATCH 48/48] test(permissions): adapt the agent-definition root posture test from main TestAgentDefRootPlacementPostureAndPolicy arrived from main (#2003) with Posture: PostureAuto, no checker, and an explicit ModeDefault session. On this branch auto refuses to start without an enforcing checker, and an explicit default session no longer inherits a process-wide allow-all, so the remote case's unlisted Shell call would ask instead of executing. The test now declares the yolo posture with the guardrails kill switch and creates the session in yolo, keeping its intent: configured Deny and Ask still apply, project rules stay out of the remote placement, and the unlisted call executes. Co-Authored-By: Claude Opus 5.5 --- internal/app/agentdef_root_composition_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/app/agentdef_root_composition_test.go b/internal/app/agentdef_root_composition_test.go index ecff8e9f16..eaabaa3a56 100644 --- a/internal/app/agentdef_root_composition_test.go +++ b/internal/app/agentdef_root_composition_test.go @@ -193,7 +193,7 @@ func TestAgentDefRootPlacementPostureAndPolicy(t *testing.T) { ), mockllm.TextTurn("done")} } llm := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { requests = append(requests, req) })}, turns...) - cfg := Config{Workspace: project, Shell: "/bin/sh", TrustProject: true, NoSoul: true, Posture: PostureAuto, PermissionConfigs: []string{settings}, PermissionsConventional: true, AgentsDirs: []string{dir}, MockProvider: llm} + cfg := Config{Workspace: project, Shell: "/bin/sh", TrustProject: true, NoSoul: true, Posture: PostureYolo, GuardrailsDisabled: true, PermissionConfigs: []string{settings}, PermissionsConventional: true, AgentsDirs: []string{dir}, MockProvider: llm} profile := server.ProfileDefault if posture == "no-fs" { profile = server.ProfileNoFS @@ -214,7 +214,9 @@ func TestAgentDefRootPlacementPostureAndPolicy(t *testing.T) { } defer built.Close() ctx := session.WithPrincipal(t.Context(), &session.Principal{Issuer: "test", Subject: "owner", GrantType: session.GrantTypeUser}) - sess, err := built.Service.CreateSessionWithProfile(ctx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, profile, server.WithAgentDefinitionName("root")) + // Allow-all is session-scoped: the session runs in yolo, where configured + // Deny and Ask still apply and an unlisted Shell call executes. + sess, err := built.Service.CreateSessionWithProfile(ctx, session.ModeYolo, session.Limits{}, server.ProviderSelector{}, profile, server.WithAgentDefinitionName("root")) if err != nil { t.Fatal(err) }