Repository: open-telemetry/opamp-go
Pull request #66 (2022-05-06 19:31:57)

Implement synchronization of AgentDescription and EffectiveConfig messages
This implements synchronization of AgentDescription and EffectiveConfig messages
according to the OpAMP spec. The hash fields are now correctly used and Report* flags
received from the Server are correctly handled.

Also added a new "expect" mode to MockServer to make writing client-server
interaction tests easier. Some existing tests may also be converted to this
new style later.

TODO:
- Implement synchronization of RemoteConfigStatus and PackageStatuses. The PR was getting too
  large, so I decided to do these 2 in a separate PR.
- Refactor WSClient and HTTPClient to reduce duplication of client logic. I moved some of it to
  a new clientcommon.go file, but more refactoring is needed - we still have to much unnecessary
  code duplication.

tigrannajaryan: @open-telemetry/opamp-go-approvers PTAL.

Patch:
diff --git a/client/client.go b/client/client.go
index c5f5736..789191b 100644
--- a/client/client.go
+++ b/client/client.go
@@ -37,12 +37,6 @@ type StartSettings struct {
 	// the server to send a remote config back.
 	LastRemoteConfigHash []byte
 
-	// The last saved effective config. If nil is passed the server will
-	// keep the last reported effective config of this agent from previous
-	// client connection sessions, if any. If there were no previous connection
-	// sessions the effective config at the server will remain unknown.
-	LastEffectiveConfig *protobufs.EffectiveConfig
-
 	LastConnectionSettingsHash []byte
 
 	// The hash of the last locally-saved server-provided packages. If nil is passed
@@ -73,7 +67,7 @@ type OpAMPClient interface {
 	//
 	// Start should be called only once. It should not be called concurrently with
 	// any other OpAMPClient methods.
-	Start(settings StartSettings) error
+	Start(ctx context.Context, settings StartSettings) error
 
 	// Stop the client. May be called only after Start() returns successfully.
 	// May be called only once.
@@ -94,12 +88,7 @@ type OpAMPClient interface {
 	// set StartSettings.AgentDescription field.
 	SetAgentDescription(descr *protobufs.AgentDescription) error
 
-	// SetEffectiveConfig sets the effective config of the Agent. The config will be
-	// included in the next status report sent to the server. The behavior regarding
-	// Start() method is exactly the same as for SetAgentAttributes() method.
-	// Note that this is one of the 3 ways the effective config can be updated on the
-	// server. The other 2 ways are:
-	//   1) via StartSettings before Start()
-	//   2) by returning an effective config in OnRemoteConfig callback.
-	SetEffectiveConfig(config *protobufs.EffectiveConfig) error
+	// UpdateEffectiveConfig fetches the current local effective config using
+	// GetEffectiveConfig callback and sends it to the Server.
+	UpdateEffectiveConfig(ctx context.Context) error
 }
diff --git a/client/helpers.go b/client/helpers.go
new file mode 100644
index 0000000..6fa567c
--- /dev/null
+++ b/client/helpers.go
@@ -0,0 +1,60 @@
+package client
+
+import (
+	"crypto/sha256"
+	"hash"
+
+	"github.com/open-telemetry/opamp-go/protobufs"
+	"google.golang.org/protobuf/encoding/protojson"
+)
+
+func writeHashKV(hash hash.Hash, kv *protobufs.KeyValue) error {
+	// To keep the implementation simple we convert the data to an equivalent JSON
+	// string and calculate the hash from the string bytes.
+	b, err := protojson.Marshal(kv)
+	if err != nil {
+		return err
+	}
+	hash.Write(b)
+	return nil
+}
+
+func writeHashKVList(hash hash.Hash, kvl []*protobufs.KeyValue) error {
+	for _, kv := range kvl {
+		err := writeHashKV(hash, kv)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// CalcHashAgentDescription calculates and sets the Hash field from the rest of the
+// fields in the message.
+func CalcHashAgentDescription(msg *protobufs.AgentDescription) error {
+	h := sha256.New()
+	err := writeHashKVList(h, msg.IdentifyingAttributes)
+	if err != nil {
+		return err
+	}
+	err = writeHashKVList(h, msg.NonIdentifyingAttributes)
+	if err != nil {
+		return err
+	}
+	msg.Hash = h.Sum(nil)
+	return nil
+}
+
+// CalcHashEffectiveConfig calculates and sets the Hash field from the rest of the
+// fields in the message.
+func CalcHashEffectiveConfig(msg *protobufs.EffectiveConfig) {
+	h := sha256.New()
+	if msg.ConfigMap != nil {
+		for k, v := range msg.ConfigMap.ConfigMap {
+			h.Write([]byte(k))
+			h.Write(v.Body)
+			h.Write([]byte(v.ContentType))
+		}
+	}
+	msg.Hash = h.Sum(nil)
+}
diff --git a/client/httpclient.go b/client/httpclient.go
index c3622d6..b339970 100644
--- a/client/httpclient.go
+++ b/client/httpclient.go
@@ -35,6 +35,9 @@ type httpClient struct {
 
 	// The looper performs HTTP request/response loop.
 	looper *internal.HTTPLooper
+
+	// Client state storage. This is needed if the Server asks to report the state.
+	clientSyncedState internal.ClientSyncedState
 }
 
 var _ OpAMPClient = (*httpClient)(nil)
@@ -47,17 +50,19 @@ func NewHTTP(logger types.Logger) *httpClient {
 	w := &httpClient{
 		logger:        logger,
 		stoppedSignal: make(chan struct{}, 1),
-		looper:        internal.NewHTTPLooper(logger),
 	}
+	w.looper = internal.NewHTTPLooper(logger, &w.clientSyncedState)
+
 	return w
 }
 
-func (w *httpClient) Start(settings StartSettings) error {
+func (w *httpClient) Start(ctx context.Context, settings StartSettings) error {
 	if w.isStarted {
 		return errAlreadyStarted
 	}
-	if settings.AgentDescription == nil {
-		return errAgentDescriptionMissing
+
+	if err := w.clientSyncedState.SetAgentDescription(settings.AgentDescription); err != nil {
+		return err
 	}
 
 	w.settings = settings
@@ -86,18 +91,11 @@ func (w *httpClient) Start(settings StartSettings) error {
 	}
 
 	// Prepare the first message to send.
-	w.looper.NextMessage().Update(
-		func(msg *protobufs.AgentToServer) {
-			if msg.StatusReport == nil {
-				msg.StatusReport = &protobufs.StatusReport{}
-			}
-			msg.StatusReport.AgentDescription = w.settings.AgentDescription
-			if msg.PackageStatuses == nil {
-				msg.PackageStatuses = &protobufs.PackageStatuses{}
-			}
-			msg.PackageStatuses.ServerProvidedAllPackagesHash = w.settings.LastServerProvidedAllPackagesHash
-		},
-	)
+	err = internal.PrepareFirstMessage(ctx, w.looper.NextMessage(), &w.clientSyncedState, w.settings.Callbacks)
+	if err != nil {
+		return err
+	}
+
 	w.looper.ScheduleSend()
 
 	w.startConnectAndRun()
@@ -129,25 +127,11 @@ func (w *httpClient) Stop(ctx context.Context) error {
 }
 
 func (w *httpClient) SetAgentDescription(descr *protobufs.AgentDescription) error {
-	if descr == nil {
-		return errAgentDescriptionMissing
-	}
-
-	// store the agent description to send on reconnect
-	w.settings.AgentDescription = descr
-	w.looper.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
-		statusReport.AgentDescription = descr
-	})
-	w.looper.ScheduleSend()
-	return nil
+	return internal.SetAgentDescription(w.looper, &w.clientSyncedState, descr)
 }
 
-func (w *httpClient) SetEffectiveConfig(config *protobufs.EffectiveConfig) error {
-	w.looper.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
-		statusReport.EffectiveConfig = config
-	})
-	w.looper.ScheduleSend()
-	return nil
+func (w *httpClient) UpdateEffectiveConfig(ctx context.Context) error {
+	return internal.UpdateEffectiveConfig(ctx, w.looper, w.settings.Callbacks)
 }
 
 func (w *httpClient) isStopping() bool {
diff --git a/client/internal/clientcommon.go b/client/internal/clientcommon.go
new file mode 100644
index 0000000..7581e6c
--- /dev/null
+++ b/client/internal/clientcommon.go
@@ -0,0 +1,96 @@
+package internal
+
+import (
+	"context"
+	"errors"
+	"fmt"
+
+	"github.com/open-telemetry/opamp-go/client/types"
+	"github.com/open-telemetry/opamp-go/protobufs"
+)
+
+var (
+	errAgentDescriptionMissing = errors.New("AgentDescription is not set")
+)
+
+// This file contains the OpAMP logic that is common between WebSocket and
+// plain HTTP transports.
+//
+// TODO: introduce a CommonClient struct that encapsulates this logic and
+// embed it in the HTTPClient and WSClient to avoid passing so many parameters
+// to these functions. There is more common OpAMP logic that we refactor and
+// move here.
+
+// PrepareFirstMessage prepares the initial state of NextMessage struct that client
+// sends when it first establishes a connection with the server.
+func PrepareFirstMessage(
+	ctx context.Context,
+	nextMessage *NextMessage,
+	clientSyncedState *ClientSyncedState,
+	callbacks types.Callbacks,
+) error {
+	cfg, err := callbacks.GetEffectiveConfig(ctx)
+	if err != nil {
+		return err
+	}
+	if cfg != nil && len(cfg.Hash) == 0 {
+		return errors.New("EffectiveConfig hash is empty")
+	}
+
+	nextMessage.Update(
+		func(msg *protobufs.AgentToServer) {
+			if msg.StatusReport == nil {
+				msg.StatusReport = &protobufs.StatusReport{}
+			}
+			msg.StatusReport.AgentDescription = clientSyncedState.AgentDescription()
+
+			msg.StatusReport.EffectiveConfig = cfg
+
+			if msg.PackageStatuses == nil {
+				msg.PackageStatuses = &protobufs.PackageStatuses{}
+			}
+
+			// TODO: set PackageStatuses.ServerProvidedAllPackagesHash field and
+			// handle the Hashes for PackageStatuses properly.
+		},
+	)
+	return nil
+}
+
+// SetAgentDescription sends a status update to the Server with the new AgentDescription
+// and remembers the AgentDescription in the client state so that it can be sent
+// to the Server when the Server asks for it.
+func SetAgentDescription(sender Sender, clientSyncedState *ClientSyncedState, descr *protobufs.AgentDescription) error {
+	// store the agent description to send on reconnect
+	if err := clientSyncedState.SetAgentDescription(descr); err != nil {
+		return err
+	}
+	sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
+		statusReport.AgentDescription = descr
+	})
+	sender.ScheduleSend()
+	return nil
+}
+
+// UpdateEffectiveConfig fetches the current local effective config using
+// GetEffectiveConfig callback and sends it to the Server using provided Sender.
+func UpdateEffectiveConfig(ctx context.Context, sender Sender, callbacks types.Callbacks) error {
+	// Fetch the locally stored config.
+	cfg, err := callbacks.GetEffectiveConfig(ctx)
+	if err != nil {
+		return fmt.Errorf("GetEffectiveConfig failed: %w", err)
+	}
+	if cfg != nil && len(cfg.Hash) == 0 {
+		return errors.New("hash field must be set, use CalcHashEffectiveConfig")
+	}
+	// Send it to the server.
+	sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
+		statusReport.EffectiveConfig = cfg
+	})
+	sender.ScheduleSend()
+
+	// Note that we do not store the EffectiveConfig anywhere else. It will be deleted
+	// from NextMessage when the message is sent. This avoids storing EffectiveConfig
+	// in memory for longer than it is needed.
+	return nil
+}
diff --git a/client/internal/clientstate.go b/client/internal/clientstate.go
new file mode 100644
index 0000000..a3998e1
--- /dev/null
+++ b/client/internal/clientstate.go
@@ -0,0 +1,69 @@
+package internal
+
+import (
+	"errors"
+	"sync"
+
+	"github.com/open-telemetry/opamp-go/protobufs"
+	"google.golang.org/protobuf/proto"
+)
+
+// ClientSyncedState stores the state of the Agent messages that the OpAMP Client needs to
+// have access to synchronize to the Server. 3 messages can be stored in this store:
+// AgentDescription, RemoteConfigStatus and PackageStatuses.
+//
+// See OpAMP spec for more details on how state synchronization works:
+// https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#agent-to-server-state-synchronization
+//
+// Note that the EffectiveConfig is subject to the same synchronization logic, however
+// it is not stored in this struct since it can be large, and we do not want to always
+// keep it in memory. To avoid storing it in memory the EffectiveConfig is supposed to be
+// stored by the Agent implementation (e.g. it can be stored on disk) and is fetched
+// via GetEffectiveConfig callback when it is needed by OpAMP client and then it is
+// discarded from memory. See implementation of UpdateEffectiveConfig().
+//
+// It is safe to call methods of this struct concurrently.
+type ClientSyncedState struct {
+	mutex sync.Mutex
+
+	agentDescription   *protobufs.AgentDescription
+	remoteConfigStatus *protobufs.RemoteConfigStatus
+	packageStatuses    *protobufs.PackageStatuses
+}
+
+func (s *ClientSyncedState) AgentDescription() *protobufs.AgentDescription {
+	defer s.mutex.Unlock()
+	s.mutex.Lock()
+	return s.agentDescription
+}
+
+func (s *ClientSyncedState) RemoteConfigStatus() *protobufs.RemoteConfigStatus {
+	defer s.mutex.Unlock()
+	s.mutex.Lock()
+	return s.remoteConfigStatus
+}
+
+func (s *ClientSyncedState) PackageStatuses() *protobufs.PackageStatuses {
+	defer s.mutex.Unlock()
+	s.mutex.Lock()
+	return s.packageStatuses
+}
+
+// SetAgentDescription sets the AgentDescription in the state.
+func (s *ClientSyncedState) SetAgentDescription(descr *protobufs.AgentDescription) error {
+	if descr == nil {
+		return errAgentDescriptionMissing
+	}
+
+	clone := proto.Clone(descr).(*protobufs.AgentDescription)
+
+	if len(descr.Hash) == 0 {
+		return errors.New("hash field must be set, use CalcHashAgentDescription")
+	}
+
+	defer s.mutex.Unlock()
+	s.mutex.Lock()
+	s.agentDescription = clone
+
+	return nil
+}
diff --git a/client/internal/httplooper.go b/client/internal/httplooper.go
index 762b16b..de3cbbd 100644
--- a/client/internal/httplooper.go
+++ b/client/internal/httplooper.go
@@ -40,19 +40,23 @@ type HTTPLooper struct {
 	hasPendingMessage chan struct{}
 
 	// The next message to send.
-	nextMessage nextMessage
+	nextMessage NextMessage
 
 	// Processor to handle received messages.
 	receiveProcessor receivedProcessor
+
+	// Client state storage. This is needed if the Server asks to report the state.
+	clientSyncedState *ClientSyncedState
 }
 
-func NewHTTPLooper(logger types.Logger) *HTTPLooper {
+func NewHTTPLooper(logger types.Logger, clientSyncedState *ClientSyncedState) *HTTPLooper {
 	h := &HTTPLooper{
 		logger:            logger,
 		client:            http.DefaultClient,
 		hasPendingMessage: make(chan struct{}, 1),
 		requestHeader:     http.Header{},
 		pollingIntervalMs: defaultPollingIntervalMs,
+		clientSyncedState: clientSyncedState,
 	}
 	h.requestHeader.Set(headerContentType, contentTypeProtobuf)
 	return h
@@ -62,16 +66,12 @@ func NewHTTPLooper(logger types.Logger) *HTTPLooper {
 // When there are no more messages to send Run will suspend until either there is
 // a new message to send or the polling interval elapses.
 // Should not be called concurrently with itself. Can be called concurrently with
-// modifying nextMessage().
+// modifying NextMessage().
 // Run continues until ctx is cancelled.
 func (h *HTTPLooper) Run(ctx context.Context, url string, callbacks types.Callbacks) {
 	h.url = url
 	h.callbacks = callbacks
-	h.receiveProcessor = receivedProcessor{
-		callbacks: callbacks,
-		logger:    h.logger,
-		sender:    h,
-	}
+	h.receiveProcessor = newReceivedProcessor(h.logger, callbacks, h, h.clientSyncedState)
 
 	for {
 		pollingTimer := time.NewTimer(time.Millisecond * time.Duration(atomic.LoadInt64(&h.pollingIntervalMs)))
@@ -95,8 +95,8 @@ func (h *HTTPLooper) Run(ctx context.Context, url string, callbacks types.Callba
 	}
 }
 
-// ScheduleSend signals to HTTPLooper that the message in nextMessage struct
-// is now ready to be sent. If there is no pending message (e.g. the nextMessage was
+// ScheduleSend signals to HTTPLooper that the message in NextMessage struct
+// is now ready to be sent. If there is no pending message (e.g. the NextMessage was
 // already sent and "pending" flag is reset) then no message will be sent.
 func (h *HTTPLooper) ScheduleSend() {
 	// Set pending flag. Don't block on writing to channel.
@@ -124,9 +124,9 @@ func (h *HTTPLooper) SetRequestHeader(key, value string) {
 	h.requestHeader.Set(key, value)
 }
 
-// nextMessage gives access to the next message that will be sent by this looper.
+// NextMessage gives access to the next message that will be sent by this looper.
 // Can be called concurrently with any other method.
-func (h *HTTPLooper) NextMessage() *nextMessage {
+func (h *HTTPLooper) NextMessage() *NextMessage {
 	return &h.nextMessage
 }
 
diff --git a/client/internal/mockserver.go b/client/internal/mockserver.go
index 46a57ab..6997651 100644
--- a/client/internal/mockserver.go
+++ b/client/internal/mockserver.go
@@ -7,6 +7,7 @@ import (
 	"net/http/httptest"
 	"net/url"
 	"testing"
+	"time"
 
 	"github.com/gorilla/websocket"
 	"github.com/stretchr/testify/assert"
@@ -16,13 +17,19 @@ import (
 	"github.com/open-telemetry/opamp-go/protobufs"
 )
 
+type receivedMessageHandler func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent
+
 type MockServer struct {
+	t           *testing.T
 	Endpoint    string
 	OnRequest   func(w http.ResponseWriter, r *http.Request)
 	OnConnect   func(r *http.Request)
 	OnWSConnect func(conn *websocket.Conn)
 	OnMessage   func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent
 	srv         *httptest.Server
+
+	expectedHandlers chan receivedMessageHandler
+	isExpectMode     bool
 }
 
 const headerContentType = "Content-Type"
@@ -31,7 +38,10 @@ const contentTypeProtobuf = "application/x-protobuf"
 var upgrader = websocket.Upgrader{}
 
 func StartMockServer(t *testing.T) *MockServer {
-	srv := &MockServer{}
+	srv := &MockServer{
+		t:                t,
+		expectedHandlers: make(chan receivedMessageHandler, 0),
+	}
 
 	m := http.NewServeMux()
 	m.HandleFunc(
@@ -67,45 +77,35 @@ func StartMockServer(t *testing.T) *MockServer {
 	return srv
 }
 
-func (srv *MockServer) handlePlainHttp(w http.ResponseWriter, r *http.Request) {
-	msgBytes, err := io.ReadAll(r.Body)
+// EnableExpectMode enables the expect mode that allows using Expect() method
+// to describe what message is expected to be received.
+func (m *MockServer) EnableExpectMode() {
+	m.isExpectMode = true
+}
 
-	var request protobufs.AgentToServer
-	err = proto.Unmarshal(msgBytes, &request)
-	if err != nil {
-		log.Fatal("cannot decode:", err)
-	}
+func (m *MockServer) handlePlainHttp(w http.ResponseWriter, r *http.Request) {
+	msgBytes, err := io.ReadAll(r.Body)
 
-	var response *protobufs.ServerToAgent
-	if srv.OnMessage != nil {
-		response = srv.OnMessage(&request)
-	}
-	if response == nil {
-		response = &protobufs.ServerToAgent{
-			InstanceUid: request.InstanceUid,
+	// We use alwaysRespond=true here because plain HTTP requests must always have
+	// a response.
+	msgBytes = m.handleReceivedBytes(msgBytes, true)
+	if msgBytes != nil {
+		// Send the response.
+		w.Header().Set(headerContentType, contentTypeProtobuf)
+		_, err = w.Write(msgBytes)
+		if err != nil {
+			log.Fatal("cannot send:", err)
 		}
 	}
-	msgBytes, err = proto.Marshal(response)
-	if err != nil {
-		log.Fatal("cannot encode:", err)
-	}
-
-	// Send the response.
-	w.Header().Set(headerContentType, contentTypeProtobuf)
-	_, err = w.Write(msgBytes)
-	if err != nil {
-		log.Fatal("cannot send:", err)
-	}
-
 }
 
-func (srv *MockServer) handleWebSocket(t *testing.T, w http.ResponseWriter, r *http.Request) {
+func (m *MockServer) handleWebSocket(t *testing.T, w http.ResponseWriter, r *http.Request) {
 	conn, err := upgrader.Upgrade(w, r, nil)
 	if err != nil {
 		return
 	}
-	if srv.OnWSConnect != nil {
-		srv.OnWSConnect(conn)
+	if m.OnWSConnect != nil {
+		m.OnWSConnect(conn)
 	}
 	for {
 		var messageType int
@@ -115,28 +115,79 @@ func (srv *MockServer) handleWebSocket(t *testing.T, w http.ResponseWriter, r *h
 		}
 		assert.EqualValues(t, websocket.BinaryMessage, messageType)
 
-		var dest protobufs.AgentToServer
-		err := proto.Unmarshal(msgBytes, &dest)
-		if err != nil {
-			log.Fatal("cannot decode:", err)
+		// We use alwaysRespond=false here because WebSocket requests must only have
+		// a response when a response is provided by the user-defined handler.
+		msgBytes = m.handleReceivedBytes(msgBytes, false)
+		if msgBytes != nil {
+			err = conn.WriteMessage(websocket.BinaryMessage, msgBytes)
+			if err != nil {
+				log.Fatal("cannot send:", err)
+			}
 		}
+	}
+}
 
-		if srv.OnMessage != nil {
-			response := srv.OnMessage(&dest)
-			if response != nil {
-				msgBytes, err := proto.Marshal(response)
-				if err != nil {
-					log.Fatal("cannot encode:", err)
-				}
-				err = conn.WriteMessage(websocket.BinaryMessage, msgBytes)
-				if err != nil {
-					log.Fatal("cannot send:", err)
-				}
-			}
+func (m *MockServer) handleReceivedBytes(msgBytes []byte, alwaysRespond bool) []byte {
+	var request protobufs.AgentToServer
+	err := proto.Unmarshal(msgBytes, &request)
+	if err != nil {
+		log.Fatal("cannot decode:", err)
+	}
+
+	var response *protobufs.ServerToAgent
+
+	if m.isExpectMode {
+		// We are in expect mode. Call user-defined handler for the message.
+		// Note that the user-defined handler may be supplied after we receive the message
+		// so we wait for the user-defined handler to provided in the expectedHandlers
+		// channel.
+		t := time.NewTimer(5 * time.Second)
+		select {
+		case h := <-m.expectedHandlers:
+			response = h(&request)
+		case <-t.C:
+			m.t.Error("Time out waiting for Expect() to handle the received message")
+		}
+	} else if m.OnMessage != nil {
+		// Not in expect mode, instead using OnMessage callback.
+		response = m.OnMessage(&request)
+	}
+
+	if alwaysRespond && response == nil {
+		// Return minimal response if the handler did not define the response, but
+		// we have to return a response.
+		response = &protobufs.ServerToAgent{
+			InstanceUid: request.InstanceUid,
 		}
 	}
+
+	if response != nil {
+		msgBytes, err = proto.Marshal(response)
+		if err != nil {
+			log.Fatal("cannot encode:", err)
+		}
+	} else {
+		msgBytes = nil
+	}
+	return msgBytes
+}
+
+// Expect defines a handler that will be called when a message is received. Expect
+// must be called when we are certain that the message will be received (if it is not
+// received a "time out" error will be recorded.
+func (m *MockServer) Expect(handler receivedMessageHandler) {
+	t := time.NewTimer(5 * time.Second)
+	select {
+	case m.expectedHandlers <- handler:
+		// push the handler to the channel.
+		// the handler will be fetched and called by handleReceivedBytes() when
+		// message is received.
+	case <-t.C:
+		m.t.Error("Time out waiting to receive a message from the client")
+	}
 }
 
 func (m *MockServer) Close() {
+	close(m.expectedHandlers)
 	m.srv.Close()
 }
diff --git a/client/internal/nextmessage.go b/client/internal/nextmessage.go
index 44c5233..dabe02c 100644
--- a/client/internal/nextmessage.go
+++ b/client/internal/nextmessage.go
@@ -7,9 +7,9 @@ import (
 	"google.golang.org/protobuf/proto"
 )
 
-// nextMessage encapsulates the next message to be sent and provides a
+// NextMessage encapsulates the next message to be sent and provides a
 // concurrency-safe interface to work with the message.
-type nextMessage struct {
+type NextMessage struct {
 	// The next message to send.
 	nextMessage protobufs.AgentToServer
 	// Indicates that nextMessage is pending to be sent.
@@ -20,7 +20,7 @@ type nextMessage struct {
 
 // Update applies the specified modifier function to the next message that
 // will be sent and marks the message as pending to be sent.
-func (s *nextMessage) Update(modifier func(msg *protobufs.AgentToServer)) {
+func (s *NextMessage) Update(modifier func(msg *protobufs.AgentToServer)) {
 	s.messageMutex.Lock()
 	modifier(&s.nextMessage)
 	s.messagePending = true
@@ -29,7 +29,7 @@ func (s *nextMessage) Update(modifier func(msg *protobufs.AgentToServer)) {
 
 // UpdateStatus applies the specified modifier function to the status report that
 // will be sent next and marks the status report as pending to be sent.
-func (s *nextMessage) UpdateStatus(modifier func(statusReport *protobufs.StatusReport)) {
+func (s *NextMessage) UpdateStatus(modifier func(statusReport *protobufs.StatusReport)) {
 	s.Update(
 		func(msg *protobufs.AgentToServer) {
 			if s.nextMessage.StatusReport == nil {
@@ -42,18 +42,45 @@ func (s *nextMessage) UpdateStatus(modifier func(statusReport *protobufs.StatusR
 
 // PopPending returns the next message to be sent, if it is pending or nil otherwise.
 // Clears the "pending" flag.
-func (s *nextMessage) PopPending() *protobufs.AgentToServer {
+func (s *NextMessage) PopPending() *protobufs.AgentToServer {
 	var msgToSend *protobufs.AgentToServer
 	s.messageMutex.Lock()
 	if s.messagePending {
 		// Clone the message to have a copy for sending and avoid blocking
-		// future updates to s.nextMessage field.
+		// future updates to s.NextMessage field.
 		msgToSend = proto.Clone(&s.nextMessage).(*protobufs.AgentToServer)
 		s.messagePending = false
 
 		// Reset fields that we do not have to send unless they change before the
-		// next report after this one.
-		s.nextMessage = protobufs.AgentToServer{}
+		// next report after this one. Keep the "hash" fields.
+		msg := protobufs.AgentToServer{
+			InstanceUid: s.nextMessage.InstanceUid,
+			StatusReport: &protobufs.StatusReport{
+				AgentDescription: &protobufs.AgentDescription{
+					Hash: s.nextMessage.StatusReport.AgentDescription.Hash,
+				},
+			},
+		}
+
+		if s.nextMessage.StatusReport.EffectiveConfig != nil {
+			msg.StatusReport.EffectiveConfig = &protobufs.EffectiveConfig{
+				Hash: s.nextMessage.StatusReport.EffectiveConfig.Hash,
+			}
+		}
+
+		if s.nextMessage.StatusReport.RemoteConfigStatus != nil {
+			msg.StatusReport.RemoteConfigStatus = &protobufs.RemoteConfigStatus{
+				Hash: s.nextMessage.StatusReport.RemoteConfigStatus.Hash,
+			}
+		}
+
+		if s.nextMessage.PackageStatuses != nil {
+			msg.PackageStatuses = &protobufs.PackageStatuses{
+				Hash: s.nextMessage.PackageStatuses.Hash,
+			}
+		}
+
+		s.nextMessage = msg
 	}
 	s.messageMutex.Unlock()
 	return msgToSend
diff --git a/client/internal/receivedprocessor.go b/client/internal/receivedprocessor.go
index 787e8e6..07b09dd 100644
--- a/client/internal/receivedprocessor.go
+++ b/client/internal/receivedprocessor.go
@@ -16,18 +16,24 @@ type receivedProcessor struct {
 
 	// A sender to cooperate with when the received message has an impact on
 	// what will be sent later.
-	sender sender
-}
-
-type sender interface {
-	// NextMessage provides access to modify the next message that will be sent.
-	NextMessage() *nextMessage
+	sender Sender
 
-	// ScheduleSend signals the sender to send a pending next message.
-	ScheduleSend()
+	// Client state storage. This is needed if the Server asks to report the state.
+	clientSyncedState *ClientSyncedState
+}
 
-	// SetInstanceUid sets a new instanceUid to be used when next message is being sent.
-	SetInstanceUid(instanceUid string) error
+func newReceivedProcessor(
+	logger types.Logger,
+	callbacks types.Callbacks,
+	sender Sender,
+	clientSyncedState *ClientSyncedState,
+) receivedProcessor {
+	return receivedProcessor{
+		logger:            logger,
+		callbacks:         callbacks,
+		sender:            sender,
+		clientSyncedState: clientSyncedState,
+	}
 }
 
 // ProcessReceivedMessage is the entry point into the processing routine. It examines
@@ -41,13 +47,20 @@ func (r *receivedProcessor) ProcessReceivedMessage(ctx context.Context, msg *pro
 			return
 		}
 
-		reportStatus := r.rcvRemoteConfig(ctx, msg.RemoteConfig, msg.Flags)
+		scheduled := r.rcvRemoteConfig(ctx, msg.RemoteConfig)
 
 		r.rcvConnectionSettings(ctx, msg.ConnectionSettings)
 		r.rcvPackagesAvailable(msg.PackagesAvailable)
 		r.rcvAgentIdentification(ctx, msg.AgentIdentification)
 
-		if reportStatus {
+		scheduled2, err := r.rcvFlags(ctx, msg.Flags)
+		if err != nil {
+			r.logger.Errorf("cannot processed received flags:%v", err)
+		}
+
+		scheduled = scheduled || scheduled2
+
+		if scheduled {
 			r.sender.ScheduleSend()
 		}
 	}
@@ -58,10 +71,54 @@ func (r *receivedProcessor) ProcessReceivedMessage(ctx context.Context, msg *pro
 	}
 }
 
+func (r *receivedProcessor) rcvFlags(
+	ctx context.Context,
+	flags protobufs.ServerToAgent_Flags,
+) (scheduleSend bool, err error) {
+	// If the Server asks to report data we fetch it from the client state storage and
+	// send to the Server.
+
+	if flags&protobufs.ServerToAgent_ReportAgentDescription != 0 {
+		r.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
+			statusReport.AgentDescription = r.clientSyncedState.AgentDescription()
+		})
+		scheduleSend = true
+	}
+
+	if flags&protobufs.ServerToAgent_ReportRemoteConfigStatus != 0 {
+		r.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
+			statusReport.RemoteConfigStatus = r.clientSyncedState.RemoteConfigStatus()
+		})
+		scheduleSend = true
+	}
+
+	if flags&protobufs.ServerToAgent_ReportPackageStatuses != 0 {
+		r.sender.NextMessage().Update(func(msg *protobufs.AgentToServer) {
+			msg.PackageStatuses = r.clientSyncedState.PackageStatuses()
+		})
+		scheduleSend = true
+	}
+
+	// The logic for EffectiveConfig is similar to the previous 3 messages however
+	// the EffectiveConfig is fetched using GetEffectiveConfig instead of
+	// from clientSyncedState. We do this to avoid keeping EffectiveConfig in-memory.
+	if flags&protobufs.ServerToAgent_ReportEffectiveConfig != 0 {
+		cfg, err := r.callbacks.GetEffectiveConfig(ctx)
+		if err != nil {
+			return false, err
+		}
+		r.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
+			statusReport.EffectiveConfig = cfg
+		})
+		scheduleSend = true
+	}
+
+	return scheduleSend, nil
+}
+
 func (r *receivedProcessor) rcvRemoteConfig(
 	ctx context.Context,
 	config *protobufs.AgentRemoteConfig,
-	flags protobufs.ServerToAgent_Flags,
 ) (reportStatus bool) {
 	effective, changed, err := r.callbacks.OnRemoteConfig(ctx, config)
 	if err != nil {
@@ -75,11 +132,8 @@ func (r *receivedProcessor) rcvRemoteConfig(
 		return true
 	}
 
-	// Report the effective configuration if it changed or if the Server explicitly
-	// asked us to report it.
-	reportEffective := changed || (flags&protobufs.ServerToAgent_ReportEffectiveConfig != 0)
-
-	if reportEffective {
+	// Report the effective configuration if it changed.
+	if changed {
 		r.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
 			statusReport.EffectiveConfig = effective
 		})
diff --git a/client/internal/sender.go b/client/internal/sender.go
new file mode 100644
index 0000000..04e57be
--- /dev/null
+++ b/client/internal/sender.go
@@ -0,0 +1,18 @@
+package internal
+
+// Sender is an interface of the sending portion of OpAMP protocol that stores
+// the NextMessage to be sent and can be ordered to send the message.
+type Sender interface {
+	// NextMessage gives access to the next message that will be sent by this Sender.
+	// Can be called concurrently with any other method.
+	NextMessage() *NextMessage
+
+	// ScheduleSend signals to Sender that the message in NextMessage struct
+	// is now ready to be sent.  The Sender should send the NextMessage as soon as possible.
+	// If there is no pending message (e.g. the NextMessage was already sent and
+	// "pending" flag is reset) then no message will be sent.
+	ScheduleSend()
+
+	// SetInstanceUid sets a new instanceUid to be used when NextMessage is being sent.
+	SetInstanceUid(instanceUid string) error
+}
diff --git a/client/internal/wsreceiver.go b/client/internal/wsreceiver.go
index 8689594..5103bc3 100644
--- a/client/internal/wsreceiver.go
+++ b/client/internal/wsreceiver.go
@@ -20,18 +20,22 @@ type wsReceiver struct {
 	processor receivedProcessor
 }
 
-func NewWSReceiver(logger types.Logger, callbacks types.Callbacks, conn *websocket.Conn, sender *WSSender) *wsReceiver {
-	return &wsReceiver{
+func NewWSReceiver(
+	logger types.Logger,
+	callbacks types.Callbacks,
+	conn *websocket.Conn,
+	sender *WSSender,
+	clientSyncedState *ClientSyncedState,
+) *wsReceiver {
+	w := &wsReceiver{
 		conn:      conn,
 		logger:    logger,
 		sender:    sender,
 		callbacks: callbacks,
-		processor: receivedProcessor{
-			callbacks: callbacks,
-			logger:    logger,
-			sender:    sender,
-		},
+		processor: newReceivedProcessor(logger, callbacks, sender, clientSyncedState),
 	}
+
+	return w
 }
 
 func (r *wsReceiver) ReceiverLoop(ctx context.Context) {
diff --git a/client/internal/wssender.go b/client/internal/wssender.go
index 2edbc54..f2f79d8 100644
--- a/client/internal/wssender.go
+++ b/client/internal/wssender.go
@@ -23,7 +23,7 @@ type WSSender struct {
 	hasMessages chan struct{}
 
 	// The next message to send.
-	nextMessage nextMessage
+	nextMessage NextMessage
 
 	// Indicates that the sender has fully stopped.
 	stopped chan struct{}
@@ -60,7 +60,7 @@ func (s *WSSender) SetInstanceUid(instanceUid string) error {
 	return nil
 }
 
-func (s *WSSender) NextMessage() *nextMessage {
+func (s *WSSender) NextMessage() *NextMessage {
 	return &s.nextMessage
 }
 
diff --git a/client/types/callbacks.go b/client/types/callbacks.go
index 49f34d0..ec06986 100644
--- a/client/types/callbacks.go
+++ b/client/types/callbacks.go
@@ -52,6 +52,11 @@ type Callbacks interface {
 		remoteConfig *protobufs.AgentRemoteConfig,
 	) (effectiveConfig *protobufs.EffectiveConfig, configChanged bool, err error)
 
+	// GetEffectiveConfig returns the current effective config. Only one
+	// GetEffectiveConfig call can be active at any time. Until GetEffectiveConfig
+	// returns it will not be called again.
+	GetEffectiveConfig(ctx context.Context) (*protobufs.EffectiveConfig, error)
+
 	// OnOpampConnectionSettings is called when the agent receives an OpAMP
 	// connection settings offer from the server. Typically the settings can specify
 	// authorization headers or TLS certificate, potentially also a different
@@ -147,6 +152,8 @@ type CallbacksStruct struct {
 		remoteConfig *protobufs.AgentRemoteConfig,
 	) (effectiveConfig *protobufs.EffectiveConfig, configChanged bool, err error)
 
+	GetEffectiveConfigFunc func(ctx context.Context) (*protobufs.EffectiveConfig, error)
+
 	OnOpampConnectionSettingsFunc func(
 		ctx context.Context,
 		settings *protobufs.ConnectionSettings,
@@ -203,6 +210,13 @@ func (c CallbacksStruct) OnRemoteConfig(
 	return nil, false, nil
 }
 
+func (c CallbacksStruct) GetEffectiveConfig(ctx context.Context) (*protobufs.EffectiveConfig, error) {
+	if c.GetEffectiveConfigFunc != nil {
+		return c.GetEffectiveConfigFunc(ctx)
+	}
+	return nil, nil
+}
+
 func (c CallbacksStruct) OnOpampConnectionSettings(
 	ctx context.Context, settings *protobufs.ConnectionSettings,
 ) error {
diff --git a/client/wsclient.go b/client/wsclient.go
index 9a2bc3f..a1a1c79 100644
--- a/client/wsclient.go
+++ b/client/wsclient.go
@@ -18,9 +18,8 @@ import (
 )
 
 var (
-	errAlreadyStarted          = errors.New("already started")
-	errCannotStopNotStarted    = errors.New("cannot stop because not started")
-	errAgentDescriptionMissing = errors.New("AgentDescription is not set")
+	errAlreadyStarted       = errors.New("already started")
+	errCannotStopNotStarted = errors.New("cannot stop because not started")
 )
 
 // wsClient is an OpAMP Client implementation for WebSocket transport.
@@ -55,6 +54,9 @@ type wsClient struct {
 
 	// The sender is responsible for sending portion of the OpAMP protocol.
 	sender *internal.WSSender
+
+	// Client state storage. This is needed if the Server asks to report the state.
+	clientSyncedState internal.ClientSyncedState
 }
 
 var _ OpAMPClient = (*wsClient)(nil)
@@ -72,16 +74,20 @@ func NewWebSocket(logger types.Logger) *wsClient {
 	return w
 }
 
-func (w *wsClient) Start(settings StartSettings) error {
+func (w *wsClient) Start(_ context.Context, settings StartSettings) error {
 	if w.isStarted {
 		return errAlreadyStarted
 	}
 
-	if settings.AgentDescription == nil {
-		return errAgentDescriptionMissing
+	if err := w.clientSyncedState.SetAgentDescription(settings.AgentDescription); err != nil {
+		return err
 	}
 
 	w.settings = settings
+	if w.settings.Callbacks == nil {
+		// Make sure it is always safe to call Callbacks.
+		w.settings.Callbacks = types.CallbacksStruct{}
+	}
 
 	var err error
 
@@ -128,7 +134,7 @@ func (w *wsClient) Stop(ctx context.Context) error {
 	w.connMutex.RUnlock()
 
 	if conn != nil {
-		conn.Close()
+		_ = conn.Close()
 	}
 	// If we are not connected by this point we may still get connected because
 	// we are racing with tryConnectOnce() func. However, after tryConnectOnce we will
@@ -145,25 +151,11 @@ func (w *wsClient) Stop(ctx context.Context) error {
 }
 
 func (w *wsClient) SetAgentDescription(descr *protobufs.AgentDescription) error {
-	if descr == nil {
-		return errAgentDescriptionMissing
-	}
-
-	// store the agent description to send on reconnect
-	w.settings.AgentDescription = descr
-	w.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
-		statusReport.AgentDescription = descr
-	})
-	w.sender.ScheduleSend()
-	return nil
+	return internal.SetAgentDescription(w.sender, &w.clientSyncedState, descr)
 }
 
-func (w *wsClient) SetEffectiveConfig(config *protobufs.EffectiveConfig) error {
-	w.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
-		statusReport.EffectiveConfig = config
-	})
-	w.sender.ScheduleSend()
-	return nil
+func (w *wsClient) UpdateEffectiveConfig(ctx context.Context) error {
+	return internal.UpdateEffectiveConfig(ctx, w.sender, w.settings.Callbacks)
 }
 
 // Try to connect once. Returns an error if connection fails and optional retryAfter
@@ -257,6 +249,7 @@ func (w *wsClient) startConnectAndRun() {
 
 	if w.isStoppingFlag {
 		// Stop() was called. Don't connect.
+		runCancel()
 		return
 	}
 	w.runCancel = runCancel
@@ -278,38 +271,32 @@ func (w *wsClient) runOneCycle(ctx context.Context) {
 	}
 
 	if w.isStopping() {
-		w.conn.Close()
+		_ = w.conn.Close()
+		return
+	}
+
+	// Prepare the first status report.
+	err := internal.PrepareFirstMessage(ctx, w.sender.NextMessage(), &w.clientSyncedState, w.settings.Callbacks)
+	if err != nil {
+		w.logger.Errorf("cannot prepare the first message:%v", err)
 		return
 	}
 
 	// Create a cancellable context for background processors.
 	procCtx, procCancel := context.WithCancel(ctx)
 
-	// Prepare the first status report.
-	w.sender.NextMessage().UpdateStatus(func(statusReport *protobufs.StatusReport) {
-		statusReport.AgentDescription = w.settings.AgentDescription
-	})
-
-	w.sender.NextMessage().Update(
-		func(msg *protobufs.AgentToServer) {
-			if msg.PackageStatuses == nil {
-				msg.PackageStatuses = &protobufs.PackageStatuses{}
-			}
-			msg.PackageStatuses.ServerProvidedAllPackagesHash = w.settings.LastServerProvidedAllPackagesHash
-		},
-	)
-
 	// Connected successfully. Start the sender. This will also send the first
 	// status report.
 	if err := w.sender.Start(procCtx, w.settings.InstanceUid, w.conn); err != nil {
 		w.logger.Errorf("Failed to send first status report: %v", err)
 		// We could not send the report, the only thing we can do is start over.
-		w.conn.Close()
+		_ = w.conn.Close()
+		procCancel()
 		return
 	}
 
 	// First status report sent. Now loop to receive and process messages.
-	r := internal.NewWSReceiver(w.logger, w.settings.Callbacks, w.conn, w.sender)
+	r := internal.NewWSReceiver(w.logger, w.settings.Callbacks, w.conn, w.sender, &w.clientSyncedState)
 	r.ReceiverLoop(ctx)
 
 	// Stop the background processors.
@@ -319,7 +306,7 @@ func (w *wsClient) runOneCycle(ctx context.Context) {
 	// read messages anymore. We need to start over.
 
 	// Close the connection to unblock the WSSender as well.
-	w.conn.Close()
+	_ = w.conn.Close()
 
 	// Wait for WSSender to stop.
 	w.sender.WaitToStop()
diff --git a/internal/examples/agent/agent/agent.go b/internal/examples/agent/agent/agent.go
index c706c4e..137872c 100644
--- a/internal/examples/agent/agent/agent.go
+++ b/internal/examples/agent/agent/agent.go
@@ -100,14 +100,16 @@ func (agent *Agent) start() error {
 			OnRemoteConfigFunc:                   agent.onRemoteConfig,
 			OnOwnTelemetryConnectionSettingsFunc: agent.onOwnTelemetryConnectionSettings,
 			OnAgentIdentificationFunc:            agent.onAgentIdentificationFunc,
+			GetEffectiveConfigFunc: func(ctx context.Context) (*protobufs.EffectiveConfig, error) {
+				return agent.composeEffectiveConfig(), nil
+			},
 		},
 		LastRemoteConfigHash: agent.remoteConfigHash,
-		LastEffectiveConfig:  agent.composeEffectiveConfig(),
 	}
 
 	agent.logger.Debugf("Starting OpAMP client...")
 
-	err := agent.opampClient.Start(settings)
+	err := agent.opampClient.Start(context.Background(), settings)
 	if err != nil {
 		return err
 	}
@@ -159,6 +161,9 @@ func (agent *Agent) createAgentIdentity() {
 			},
 		},
 	}
+	if err := client.CalcHashAgentDescription(agent.agentDescription); err != nil {
+		agent.logger.Errorf("Cannot calculate the hash: %v", err)
+	}
 }
 
 func (agent *Agent) updateAgentIdentity(instanceId ulid.ULID) {
diff --git a/internal/proto/opamp.proto b/internal/proto/opamp.proto
index 4fc8882..2bb802e 100644
--- a/internal/proto/opamp.proto
+++ b/internal/proto/opamp.proto
@@ -95,15 +95,21 @@ message ServerToAgent {
         // particular bit of information in the last status report (which is an allowed
         // optimization) but the server does not have it (e.g. was restarted and lost state).
 
-        // The server asks the agent to report effective config. This bit MUST NOT be
+        // The server asks the agent to report full AgentDescription.
+        ReportAgentDescription   = 0x00000001;
+        // The server asks the agent to report full EffectiveConfig. This bit MUST NOT be
         // set if the Agent indicated it cannot report effective config by setting
         // the ReportsEffectiveConfig bit to 0 in StatusReport.capabilities field.
-        ReportEffectiveConfig = 0x00000001;
+        ReportEffectiveConfig    = 0x00000002;
 
-        // The server asks the agent to report package statuses. This bit MUST NOT be
+        // The server asks the agent to report full RemoteConfigStatus. This bit MUST NOT be
+        // set if the Agent indicated it cannot accept remote config by setting
+        // the AcceptsRemoteConfig bit to 0 in StatusReport.capabilities field.
+        ReportRemoteConfigStatus = 0x00000004;
+        // The server asks the agent to report full PackageStatuses. This bit MUST NOT be
         // set if the Agent indicated it cannot report package status by setting
-        // the ReportsPackagesStatus bit to 0 in StatusReport.capabilities field.
-        ReportPackagesStatus  = 0x00000002;
+        // the ReportsPackageStatuses bit to 0 in StatusReport.capabilities field.
+        ReportPackageStatuses    = 0x00000008;
     }
     // Bit flags as defined by Flags bit masks.
     Flags flags = 6;
@@ -436,6 +442,10 @@ message ServerToAgentCommand {
 // Status reporting
 
 message AgentDescription {
+    // The hash of the content of all other fields (even if the other fields are omitted
+    // for compression).
+    bytes hash = 1;
+
     // Attributes that identify the agent.
     // Keys/values are according to OpenTelemetry semantic conventions, see:
     // https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions
@@ -456,7 +466,7 @@ message AgentDescription {
     // telemetry. The combination of identifying attributes SHOULD be sufficient to
     // uniquely identify the Agent's own telemetry in the destination system to which
     // the Agent sends its own telemetry.
-    repeated KeyValue identifying_attributes = 1;
+    repeated KeyValue identifying_attributes = 2;
 
     // Attributes that do not necessarily identify the Agent but help describe
     // where it runs.
@@ -468,7 +478,7 @@ message AgentDescription {
     //   environment it runs in.
     // - any user-defined attributes that the end user would like to associate
     //   with this agent.
-    repeated KeyValue non_identifying_attributes = 2;
+    repeated KeyValue non_identifying_attributes = 3;
 
     // TODO: add ability to specify related entities (such as the Service the Agent is
     // is responsible/associated with).
@@ -516,7 +526,7 @@ enum AgentCapabilities {
     // The Agent can accept package offers.
     AcceptsPackages                = 0x00000008;
     // The Agent can report package status.
-    ReportsPackagesStatus          = 0x00000010;
+    ReportsPackageStatuses         = 0x00000010;
     // The Agent can report own trace to the destination specified by
     // the Server via ConnectionSettingsOffers.own_traces field.
     ReportsOwnTraces               = 0x00000020;
@@ -557,11 +567,15 @@ message EffectiveConfig {
 }
 
 message RemoteConfigStatus {
+    // The hash of the content of all other fields (even if the other fields are omitted
+    // for compression).
+    bytes hash = 1;
+
     // The hash of the remote config that was last received by this agent from the
     // management server. The server SHOULD compare this hash with the config hash it has
     // for the agent and if the hashes are different the server MUST include
     // the remote_config field in the response in the DataForAgent message.
-    bytes last_remote_config_hash = 1;
+    bytes last_remote_config_hash = 2;
 
     enum Status {
         // Remote config was successfully applied by the Agent.
@@ -574,17 +588,21 @@ message RemoteConfigStatus {
         // See error_message for more details.
         Failed = 2;
     }
-    Status status = 2;
+    Status status = 3;
 
-    string error_message = 3;
+    string error_message = 4;
 }
 
 // The PackageStatuses message describes the status of all packages that the agent
 // has or was offered.
 message PackageStatuses {
+    // The hash of the content of all other fields (even if the other fields are omitted
+    // for compression).
+    bytes hash = 1;
+
     // A map of PackageStatus messages, where the keys are package names.
     // The key MUST match the name field of PackageStatus message.
-    map<string, PackageStatus> packages = 1;
+    map<string, PackageStatus> packages = 2;
 
     // The aggregate hash of all packages that this Agent previously received from the
     // server via PackagesAvailable message.
@@ -592,7 +610,7 @@ message PackageStatuses {
     // The server SHOULD compare this hash to the aggregate hash of all packages that
     // it has for this Agent and if the hashes are different the server SHOULD send
     // an PackagesAvailable message to the agent.
-    bytes server_provided_all_packages_hash = 2;
+    bytes server_provided_all_packages_hash = 3;
 }
 
 // The status of a single package.
diff --git a/protobufs/opamp.pb.go b/protobufs/opamp.pb.go
index 0898409..242ef4b 100644
--- a/protobufs/opamp.pb.go
+++ b/protobufs/opamp.pb.go
@@ -120,7 +120,7 @@ const (
 	// The Agent can accept package offers.
 	AgentCapabilities_AcceptsPackages AgentCapabilities = 8
 	// The Agent can report package status.
-	AgentCapabilities_ReportsPackagesStatus AgentCapabilities = 16
+	AgentCapabilities_ReportsPackageStatuses AgentCapabilities = 16
 	// The Agent can report own trace to the destination specified by
 	// the Server via ConnectionSettingsOffers.own_traces field.
 	AgentCapabilities_ReportsOwnTraces AgentCapabilities = 32
@@ -148,7 +148,7 @@ var (
 		2:    "AcceptsRemoteConfig",
 		4:    "ReportsEffectiveConfig",
 		8:    "AcceptsPackages",
-		16:   "ReportsPackagesStatus",
+		16:   "ReportsPackageStatuses",
 		32:   "ReportsOwnTraces",
 		64:   "ReportsOwnMetrics",
 		128:  "ReportsOwnLogs",
@@ -162,7 +162,7 @@ var (
 		"AcceptsRemoteConfig":            2,
 		"ReportsEffectiveConfig":         4,
 		"AcceptsPackages":                8,
-		"ReportsPackagesStatus":          16,
+		"ReportsPackageStatuses":         16,
 		"ReportsOwnTraces":               32,
 		"ReportsOwnMetrics":              64,
 		"ReportsOwnLogs":                 128,
@@ -251,27 +251,37 @@ type ServerToAgent_Flags int32
 
 const (
 	ServerToAgent_FlagsUnspecified ServerToAgent_Flags = 0
-	// The server asks the agent to report effective config. This bit MUST NOT be
+	// The server asks the agent to report full AgentDescription.
+	ServerToAgent_ReportAgentDescription ServerToAgent_Flags = 1
+	// The server asks the agent to report full EffectiveConfig. This bit MUST NOT be
 	// set if the Agent indicated it cannot report effective config by setting
 	// the ReportsEffectiveConfig bit to 0 in StatusReport.capabilities field.
-	ServerToAgent_ReportEffectiveConfig ServerToAgent_Flags = 1
-	// The server asks the agent to report package statuses. This bit MUST NOT be
+	ServerToAgent_ReportEffectiveConfig ServerToAgent_Flags = 2
+	// The server asks the agent to report full RemoteConfigStatus. This bit MUST NOT be
+	// set if the Agent indicated it cannot accept remote config by setting
+	// the AcceptsRemoteConfig bit to 0 in StatusReport.capabilities field.
+	ServerToAgent_ReportRemoteConfigStatus ServerToAgent_Flags = 4
+	// The server asks the agent to report full PackageStatuses. This bit MUST NOT be
 	// set if the Agent indicated it cannot report package status by setting
-	// the ReportsPackagesStatus bit to 0 in StatusReport.capabilities field.
-	ServerToAgent_ReportPackagesStatus ServerToAgent_Flags = 2
+	// the ReportsPackageStatuses bit to 0 in StatusReport.capabilities field.
+	ServerToAgent_ReportPackageStatuses ServerToAgent_Flags = 8
 )
 
 // Enum value maps for ServerToAgent_Flags.
 var (
 	ServerToAgent_Flags_name = map[int32]string{
 		0: "FlagsUnspecified",
-		1: "ReportEffectiveConfig",
-		2: "ReportPackagesStatus",
+		1: "ReportAgentDescription",
+		2: "ReportEffectiveConfig",
+		4: "ReportRemoteConfigStatus",
+		8: "ReportPackageStatuses",
 	}
 	ServerToAgent_Flags_value = map[string]int32{
-		"FlagsUnspecified":      0,
-		"ReportEffectiveConfig": 1,
-		"ReportPackagesStatus":  2,
+		"FlagsUnspecified":         0,
+		"ReportAgentDescription":   1,
+		"ReportEffectiveConfig":    2,
+		"ReportRemoteConfigStatus": 4,
+		"ReportPackageStatuses":    8,
 	}
 )
 
@@ -1751,6 +1761,9 @@ type AgentDescription struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
+	// The hash of the content of all other fields (even if the other fields are omitted
+	// for compression).
+	Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
 	// Attributes that identify the agent.
 	// Keys/values are according to OpenTelemetry semantic conventions, see:
 	// https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions
@@ -1771,7 +1784,7 @@ type AgentDescription struct {
 	// telemetry. The combination of identifying attributes SHOULD be sufficient to
 	// uniquely identify the Agent's own telemetry in the destination system to which
 	// the Agent sends its own telemetry.
-	IdentifyingAttributes []*KeyValue `protobuf:"bytes,1,rep,name=identifying_attributes,json=identifyingAttributes,proto3" json:"identifying_attributes,omitempty"`
+	IdentifyingAttributes []*KeyValue `protobuf:"bytes,2,rep,name=identifying_attributes,json=identifyingAttributes,proto3" json:"identifying_attributes,omitempty"`
 	// Attributes that do not necessarily identify the Agent but help describe
 	// where it runs.
 	// The following attributes SHOULD be included:
@@ -1782,7 +1795,7 @@ type AgentDescription struct {
 	//   environment it runs in.
 	// - any user-defined attributes that the end user would like to associate
 	//   with this agent.
-	NonIdentifyingAttributes []*KeyValue `protobuf:"bytes,2,rep,name=non_identifying_attributes,json=nonIdentifyingAttributes,proto3" json:"non_identifying_attributes,omitempty"`
+	NonIdentifyingAttributes []*KeyValue `protobuf:"bytes,3,rep,name=non_identifying_attributes,json=nonIdentifyingAttributes,proto3" json:"non_identifying_attributes,omitempty"`
 }
 
 func (x *AgentDescription) Reset() {
@@ -1817,6 +1830,13 @@ func (*AgentDescription) Descriptor() ([]byte, []int) {
 	return file_opamp_proto_rawDescGZIP(), []int{14}
 }
 
+func (x *AgentDescription) GetHash() []byte {
+	if x != nil {
+		return x.Hash
+	}
+	return nil
+}
+
 func (x *AgentDescription) GetIdentifyingAttributes() []*KeyValue {
 	if x != nil {
 		return x.IdentifyingAttributes
@@ -1993,13 +2013,16 @@ type RemoteConfigStatus struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
+	// The hash of the content of all other fields (even if the other fields are omitted
+	// for compression).
+	Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
 	// The hash of the remote config that was last received by this agent from the
 	// management server. The server SHOULD compare this hash with the config hash it has
 	// for the agent and if the hashes are different the server MUST include
 	// the remote_config field in the response in the DataForAgent message.
-	LastRemoteConfigHash []byte                    `protobuf:"bytes,1,opt,name=last_remote_config_hash,json=lastRemoteConfigHash,proto3" json:"last_remote_config_hash,omitempty"`
-	Status               RemoteConfigStatus_Status `protobuf:"varint,2,opt,name=status,proto3,enum=opamp.proto.RemoteConfigStatus_Status" json:"status,omitempty"`
-	ErrorMessage         string                    `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
+	LastRemoteConfigHash []byte                    `protobuf:"bytes,2,opt,name=last_remote_config_hash,json=lastRemoteConfigHash,proto3" json:"last_remote_config_hash,omitempty"`
+	Status               RemoteConfigStatus_Status `protobuf:"varint,3,opt,name=status,proto3,enum=opamp.proto.RemoteConfigStatus_Status" json:"status,omitempty"`
+	ErrorMessage         string                    `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
 }
 
 func (x *RemoteConfigStatus) Reset() {
@@ -2034,6 +2057,13 @@ func (*RemoteConfigStatus) Descriptor() ([]byte, []int) {
 	return file_opamp_proto_rawDescGZIP(), []int{17}
 }
 
+func (x *RemoteConfigStatus) GetHash() []byte {
+	if x != nil {
+		return x.Hash
+	}
+	return nil
+}
+
 func (x *RemoteConfigStatus) GetLastRemoteConfigHash() []byte {
 	if x != nil {
 		return x.LastRemoteConfigHash
@@ -2062,16 +2092,19 @@ type PackageStatuses struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
+	// The hash of the content of all other fields (even if the other fields are omitted
+	// for compression).
+	Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
 	// A map of PackageStatus messages, where the keys are package names.
 	// The key MUST match the name field of PackageStatus message.
-	Packages map[string]*PackageStatus `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Packages map[string]*PackageStatus `protobuf:"bytes,2,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 	// The aggregate hash of all packages that this Agent previously received from the
 	// server via PackagesAvailable message.
 	//
 	// The server SHOULD compare this hash to the aggregate hash of all packages that
 	// it has for this Agent and if the hashes are different the server SHOULD send
 	// an PackagesAvailable message to the agent.
-	ServerProvidedAllPackagesHash []byte `protobuf:"bytes,2,opt,name=server_provided_all_packages_hash,json=serverProvidedAllPackagesHash,proto3" json:"server_provided_all_packages_hash,omitempty"`
+	ServerProvidedAllPackagesHash []byte `protobuf:"bytes,3,opt,name=server_provided_all_packages_hash,json=serverProvidedAllPackagesHash,proto3" json:"server_provided_all_packages_hash,omitempty"`
 }
 
 func (x *PackageStatuses) Reset() {
@@ -2106,6 +2139,13 @@ func (*PackageStatuses) Descriptor() ([]byte, []int) {
 	return file_opamp_proto_rawDescGZIP(), []int{18}
 }
 
+func (x *PackageStatuses) GetHash() []byte {
+	if x != nil {
+		return x.Hash
+	}
+	return nil
+}
+
 func (x *PackageStatuses) GetPackages() map[string]*PackageStatus {
 	if x != nil {
 		return x.Packages
@@ -2512,7 +2552,7 @@ var file_opamp_proto_rawDesc = []byte{
 	0x46, 0x6c, 0x61, 0x67, 0x73, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64,
 	0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x73,
 	0x74, 0x61, 0x6e, 0x63, 0x65, 0x55, 0x69, 0x64, 0x10, 0x01, 0x22, 0x11, 0x0a, 0x0f, 0x41, 0x67,
-	0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x22, 0xca, 0x05,
+	0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x22, 0x86, 0x06,
 	0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12,
 	0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x75, 0x69, 0x64, 0x18,
 	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x55,
@@ -2552,155 +2592,160 @@ var file_opamp_proto_rawDesc = []byte{
 	0x6d, 0x61, 0x6e, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6f, 0x70, 0x61,
 	0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54,
 	0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x07, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x52, 0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12,
-	0x14, 0x0a, 0x10, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66,
-	0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45,
-	0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01,
-	0x12, 0x18, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
-	0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x02, 0x22, 0x97, 0x03, 0x0a, 0x12, 0x43,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x8d, 0x01, 0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73,
+	0x12, 0x14, 0x0a, 0x10, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69,
+	0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
+	0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+	0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x66, 0x66, 0x65,
+	0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x02, 0x12, 0x1c, 0x0a,
+	0x18, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e,
+	0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x52,
+	0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x65, 0x73, 0x10, 0x08, 0x22, 0x97, 0x03, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x0a,
+	0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64,
+	0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x64, 0x65, 0x73,
+	0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
+	0x12, 0x2e, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
+	0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
+	0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x45,
+	0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79,
+	0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14,
+	0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61,
+	0x64, 0x65, 0x72, 0x73, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65,
+	0x72, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+	0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x25, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43,
 	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70,
-	0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x07, 0x68, 0x65, 0x61,
-	0x64, 0x65, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x65, 0x6e,
-	0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72,
-	0x6f, 0x78, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0d, 0x70,
-	0x72, 0x6f, 0x78, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x48,
-	0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
-	0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70,
-	0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72,
-	0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
-	0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x06,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74,
-	0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61,
-	0x67, 0x73, 0x22, 0x40, 0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x05, 0x0a, 0x01, 0x5f,
-	0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x10, 0x01, 0x12, 0x14,
-	0x0a, 0x10, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53,
-	0x65, 0x74, 0x10, 0x02, 0x22, 0x38, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12,
-	0x2d, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x13, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48,
-	0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x30,
-	0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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,
-	0x22, 0x74, 0x0a, 0x0e, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
-	0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
-	0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b,
-	0x65, 0x79, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
-	0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x61, 0x50, 0x75, 0x62,
-	0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0xf3, 0x03, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4f, 0x66, 0x66,
-	0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x35, 0x0a, 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53,
-	0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x12, 0x40,
-	0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74,
-	0x69, 0x6e, 0x67, 0x73, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-	0x12, 0x3e, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74,
-	0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73,
-	0x12, 0x3a, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01,
+	0x73, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x40,
+	0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x05, 0x0a, 0x01, 0x5f, 0x10, 0x00, 0x12, 0x1a,
+	0x0a, 0x16, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64,
+	0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x72,
+	0x6f, 0x78, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x10, 0x02,
+	0x22, 0x38, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x68,
+	0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6f,
+	0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65,
+	0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x30, 0x0a, 0x06, 0x48, 0x65,
+	0x61, 0x64, 0x65, 0x72, 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, 0x22, 0x74, 0x0a, 0x0e,
+	0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1d,
+	0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a,
+	0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x22,
+	0x0a, 0x0d, 0x63, 0x61, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
+	0x65, 0x79, 0x22, 0xf3, 0x03, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
+	0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x12,
+	0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68,
+	0x61, 0x73, 0x68, 0x12, 0x35, 0x0a, 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01,
 	0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 	0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69,
-	0x6e, 0x67, 0x73, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x68, 0x0a, 0x11,
-	0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
-	0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
-	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x2e, 0x4f,
-	0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45,
-	0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x64, 0x0a, 0x15, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43,
-	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+	0x6e, 0x67, 0x73, 0x52, 0x05, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x12, 0x40, 0x0a, 0x0b, 0x6f, 0x77,
+	0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f,
+	0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
+	0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x3e, 0x0a, 0x0a,
+	0x6f, 0x77, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
 	0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43,
 	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, 0x01, 0x0a,
-	0x11, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
-	0x6c, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c,
-	0x61, 0x62, 0x6c, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74,
-	0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11,
-	0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x68, 0x61, 0x73,
-	0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x61, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b,
-	0x61, 0x67, 0x65, 0x73, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x5a, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b,
-	0x61, 0x67, 0x65, 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, 0x33, 0x0a, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6f, 0x70, 0x61,
-	0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-	0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x3a, 0x02, 0x38, 0x01, 0x22, 0xe8, 0x01, 0x0a, 0x10, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-	0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x79, 0x70,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x76, 0x61,
-	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x54, 0x79,
-	0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 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, 0x31, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x1d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44,
-	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52,
-	0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x34, 0x0a, 0x0b, 0x50, 0x61, 0x63,
-	0x6b, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x6f, 0x70, 0x4c,
-	0x65, 0x76, 0x65, 0x6c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x10, 0x00, 0x12, 0x10, 0x0a,
-	0x0c, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x10, 0x01, 0x22,
-	0x76, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x46,
-	0x69, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5f,
-	0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c,
-	0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
-	0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f,
-	0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67,
-	0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69,
-	0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xef, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x39, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e,
-	0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
-	0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72,
-	0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
-	0x37, 0x0a, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x09, 0x72,
-	0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x34, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
-	0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0e, 0x0a,
-	0x0a, 0x42, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x0f, 0x0a,
-	0x0b, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x42, 0x09,
-	0x0a, 0x07, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x43, 0x0a, 0x09, 0x52, 0x65, 0x74,
-	0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f,
-	0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
-	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x72, 0x65, 0x74, 0x72, 0x79, 0x41, 0x66,
-	0x74, 0x65, 0x72, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x75,
-	0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74,
-	0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54,
-	0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x1a, 0x0a, 0x0b, 0x43, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74,
-	0x61, 0x72, 0x74, 0x10, 0x00, 0x22, 0xb5, 0x01, 0x0a, 0x10, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44,
-	0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x16, 0x69, 0x64,
+	0x73, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x08,
+	0x6f, 0x77, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f,
+	0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e,
+	0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52,
+	0x07, 0x6f, 0x77, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x68, 0x0a, 0x11, 0x6f, 0x74, 0x68, 0x65,
+	0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74,
+	0x69, 0x6e, 0x67, 0x73, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72,
+	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
+	0x52, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
+	0x6e, 0x73, 0x1a, 0x64, 0x0a, 0x15, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x35, 0x0a,
+	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f,
+	0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x63,
+	0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x48,
+	0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x2c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50,
+	0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+	0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08,
+	0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x5f,
+	0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0c, 0x52, 0x0f, 0x61, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73,
+	0x48, 0x61, 0x73, 0x68, 0x1a, 0x5a, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 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, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x76, 0x61, 0x69,
+	0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
+	0x22, 0xe8, 0x01, 0x0a, 0x10, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x76, 0x61, 0x69,
+	0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
+	0x6c, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
+	0x74, 0x79, 0x70, 0x65, 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, 0x31,
+	0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6f,
+	0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
+	0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c,
+	0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52,
+	0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x34, 0x0a, 0x0b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+	0x54, 0x79, 0x70, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x6f, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c,
+	0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x64, 0x64,
+	0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x10, 0x01, 0x22, 0x76, 0x0a, 0x10, 0x44,
+	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12,
+	0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55,
+	0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61,
+	0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+	0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
+	0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74,
+	0x75, 0x72, 0x65, 0x22, 0xef, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72,
+	0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x74,
+	0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x61, 0x6d,
+	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72,
+	0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65,
+	0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65,
+	0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x72,
+	0x65, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x16, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
+	0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x09, 0x72, 0x65, 0x74, 0x72, 0x79,
+	0x49, 0x6e, 0x66, 0x6f, 0x22, 0x34, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07,
+	0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x42, 0x61, 0x64,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x6e, 0x61,
+	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x42, 0x09, 0x0a, 0x07, 0x44, 0x65,
+	0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x43, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x61, 0x66, 0x74, 0x65,
+	0x72, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x15, 0x72, 0x65, 0x74, 0x72, 0x79, 0x41, 0x66, 0x74, 0x65, 0x72, 0x4e,
+	0x61, 0x6e, 0x6f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x75, 0x0a, 0x14, 0x53, 0x65,
+	0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x12, 0x41, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x2d, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
+	0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52,
+	0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x1a, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x10,
+	0x00, 0x22, 0xc9, 0x01, 0x0a, 0x10, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72,
+	0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x4c, 0x0a, 0x16, 0x69, 0x64,
 	0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
-	0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61,
+	0x75, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f, 0x70, 0x61,
 	0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75,
 	0x65, 0x52, 0x15, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x41, 0x74,
 	0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x53, 0x0a, 0x1a, 0x6e, 0x6f, 0x6e, 0x5f,
 	0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x74, 0x72,
-	0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f,
+	0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6f,
 	0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61,
 	0x6c, 0x75, 0x65, 0x52, 0x18, 0x6e, 0x6f, 0x6e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79,
 	0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0xba, 0x02,
@@ -2729,127 +2774,130 @@ var file_opamp_proto_rawDesc = []byte{
 	0x68, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x18,
 	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d,
-	0x61, 0x70, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x22, 0xe1, 0x01,
+	0x61, 0x70, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x22, 0xf5, 0x01,
 	0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74,
-	0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x6d,
-	0x6f, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74,
-	0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3e, 0x0a, 0x06, 0x73,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x6f, 0x70,
-	0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65,
-	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61,
-	0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65,
-	0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x22, 0x2f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x70,
-	0x70, 0x6c, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x70, 0x70, 0x6c, 0x79,
-	0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10,
-	0x02, 0x22, 0xfc, 0x01, 0x0a, 0x0f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61,
-	0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61,
-	0x74, 0x75, 0x73, 0x65, 0x73, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e,
-	0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x48, 0x0a,
-	0x21, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
-	0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x68, 0x61,
-	0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
-	0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b, 0x61,
-	0x67, 0x65, 0x73, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x57, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61,
-	0x67, 0x65, 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, 0x30, 0x0a, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6f, 0x70, 0x61, 0x6d,
-	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
-	0x22, 0x8b, 0x03, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 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, 0x2a, 0x0a, 0x11, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f,
-	0x68, 0x61, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x5f,
-	0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x61, 0x67, 0x65, 0x6e,
-	0x74, 0x48, 0x61, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
-	0x4f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e,
-	0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64,
-	0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x73, 0x65, 0x72,
-	0x76, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x39,
-	0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21,
-	0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63,
-	0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75,
-	0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72,
-	0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4e,
-	0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74,
-	0x61, 0x6c, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49,
-	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x49,
-	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x03, 0x22, 0x3f,
-	0x0a, 0x13, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x6e, 0x73,
-	0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0e, 0x6e, 0x65, 0x77, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x55, 0x69, 0x64, 0x22,
-	0x69, 0x0a, 0x11, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x12, 0x33, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61,
-	0x70, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a,
-	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x61, 0x73, 0x68, 0x22, 0xb7, 0x01, 0x0a, 0x0e, 0x41,
-	0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x12, 0x49, 0x0a,
-	0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x2e, 0x43,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x63,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x1a, 0x5a, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
-	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6f, 0x70,
-	0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x3a, 0x02, 0x38, 0x01, 0x22, 0x48, 0x0a, 0x0f, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63,
-	0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x2a, 0xc9,
-	0x01, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c,
-	0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69,
-	0x66, 0x69, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69,
-	0x6c, 0x69, 0x74, 0x79, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74,
-	0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x66, 0x66,
-	0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10,
-	0x02, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x45, 0x66, 0x66, 0x65,
-	0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x04, 0x12, 0x12, 0x0a,
-	0x0e, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x10,
-	0x08, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x50, 0x61, 0x63, 0x6b,
-	0x61, 0x67, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x10, 0x12, 0x1c, 0x0a, 0x18,
-	0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
-	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x20, 0x2a, 0xd3, 0x02, 0x0a, 0x11, 0x41,
-	0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73,
-	0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41,
-	0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x10, 0x00,
-	0x12, 0x11, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75,
-	0x73, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x52, 0x65,
-	0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16,
-	0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65,
-	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x63, 0x63, 0x65,
-	0x70, 0x74, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x10, 0x08, 0x12, 0x19, 0x0a,
-	0x15, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73,
-	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x10, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f,
-	0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x10, 0x20, 0x12, 0x15,
-	0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x72,
-	0x69, 0x63, 0x73, 0x10, 0x40, 0x12, 0x13, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73,
-	0x4f, 0x77, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x10, 0x80, 0x01, 0x12, 0x23, 0x0a, 0x1e, 0x41, 0x63,
-	0x63, 0x65, 0x70, 0x74, 0x73, 0x4f, 0x70, 0x41, 0x4d, 0x50, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
-	0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x80, 0x02, 0x12,
-	0x23, 0x0a, 0x1e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43,
-	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x10, 0x80, 0x04, 0x12, 0x1a, 0x0a, 0x15, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x52,
-	0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x80, 0x08,
-	0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f,
-	0x70, 0x65, 0x6e, 0x2d, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2f, 0x6f, 0x70,
-	0x61, 0x6d, 0x70, 0x2d, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73,
-	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x35, 0x0a, 0x17, 0x6c, 0x61, 0x73, 0x74,
+	0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x68,
+	0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x52,
+	0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12,
+	0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x26, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
+	0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
+	0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x22, 0x2f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b,
+	0x0a, 0x07, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x41,
+	0x70, 0x70, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x61, 0x69,
+	0x6c, 0x65, 0x64, 0x10, 0x02, 0x22, 0x90, 0x02, 0x0a, 0x0f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
+	0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73,
+	0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x46, 0x0a,
+	0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x2a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61,
+	0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x2e, 0x50, 0x61,
+	0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63,
+	0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x21, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
+	0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x63,
+	0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
+	0x52, 0x1d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
+	0x41, 0x6c, 0x6c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x48, 0x61, 0x73, 0x68, 0x1a,
+	0x57, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 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, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x1a, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8b, 0x03, 0x0a, 0x0d, 0x50, 0x61, 0x63,
+	0x6b, 0x61, 0x67, 0x65, 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, 0x2a,
+	0x0a, 0x11, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x67, 0x65, 0x6e, 0x74,
+	0x48, 0x61, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x67,
+	0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x48, 0x61, 0x73, 0x68,
+	0x12, 0x34, 0x0a, 0x16, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72,
+	0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x14, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x56,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+	0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x0c, 0x52, 0x11, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x65, 0x72,
+	0x65, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4e, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x12, 0x0d, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12,
+	0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+	0x67, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x69, 0x6e,
+	0x67, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x46, 0x61,
+	0x69, 0x6c, 0x65, 0x64, 0x10, 0x03, 0x22, 0x3f, 0x0a, 0x13, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49,
+	0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a,
+	0x10, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x75, 0x69,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x65, 0x77, 0x49, 0x6e, 0x73, 0x74,
+	0x61, 0x6e, 0x63, 0x65, 0x55, 0x69, 0x64, 0x22, 0x69, 0x0a, 0x11, 0x41, 0x67, 0x65, 0x6e, 0x74,
+	0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x33, 0x0a, 0x06,
+	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f,
+	0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74,
+	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x61,
+	0x73, 0x68, 0x22, 0xb7, 0x01, 0x0a, 0x0e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66,
+	0x69, 0x67, 0x4d, 0x61, 0x70, 0x12, 0x49, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
+	0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6f, 0x70, 0x61, 0x6d,
+	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+	0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70,
+	0x1a, 0x5a, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74,
+	0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x69, 0x6c,
+	0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x48, 0x0a, 0x0f,
+	0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x12,
+	0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62,
+	0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74,
+	0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+	0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x2a, 0xc9, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a,
+	0x1b, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76,
+	0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x10, 0x00, 0x12, 0x11,
+	0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10,
+	0x01, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x74,
+	0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x63, 0x63,
+	0x65, 0x70, 0x74, 0x73, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e,
+	0x66, 0x69, 0x67, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x50,
+	0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x10, 0x08, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x63, 0x63,
+	0x65, 0x70, 0x74, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x10, 0x10, 0x12, 0x1c, 0x0a, 0x18, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x43, 0x6f,
+	0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
+	0x10, 0x20, 0x2a, 0xd4, 0x02, 0x0a, 0x11, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61,
+	0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x70, 0x61,
+	0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x6f,
+	0x72, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x41,
+	0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66,
+	0x69, 0x67, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x45,
+	0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x04,
+	0x12, 0x13, 0x0a, 0x0f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x50, 0x61, 0x63, 0x6b, 0x61,
+	0x67, 0x65, 0x73, 0x10, 0x08, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73,
+	0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x10,
+	0x10, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x54,
+	0x72, 0x61, 0x63, 0x65, 0x73, 0x10, 0x20, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x72,
+	0x74, 0x73, 0x4f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x10, 0x40, 0x12, 0x13,
+	0x0a, 0x0e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x4f, 0x77, 0x6e, 0x4c, 0x6f, 0x67, 0x73,
+	0x10, 0x80, 0x01, 0x12, 0x23, 0x0a, 0x1e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x4f, 0x70,
+	0x41, 0x4d, 0x50, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74,
+	0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x80, 0x02, 0x12, 0x23, 0x0a, 0x1e, 0x41, 0x63, 0x63, 0x65,
+	0x70, 0x74, 0x73, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
+	0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x80, 0x04, 0x12, 0x1a, 0x0a,
+	0x15, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x80, 0x08, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74,
+	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x2d, 0x74, 0x65, 0x6c,
+	0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2f, 0x6f, 0x70, 0x61, 0x6d, 0x70, 0x2d, 0x67, 0x6f, 0x2f,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x33,
 }
 
 var (


Test patch:
diff --git a/client/clientimpl_test.go b/client/clientimpl_test.go
index 05e19db..7dc67c2 100644
--- a/client/clientimpl_test.go
+++ b/client/clientimpl_test.go
@@ -2,6 +2,7 @@ package client
 
 import (
 	"context"
+	"log"
 	"math/rand"
 	"net/http"
 	"net/url"
@@ -10,7 +11,6 @@ import (
 	"time"
 
 	ulid "github.com/oklog/ulid/v2"
-	"github.com/open-telemetry/opamp-go/protobufshelpers"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"google.golang.org/protobuf/proto"
@@ -23,6 +23,22 @@ import (
 
 const retryAfterHTTPHeader = "Retry-After"
 
+func createAgentDescr() *protobufs.AgentDescription {
+	agentDescr := &protobufs.AgentDescription{
+		IdentifyingAttributes: []*protobufs.KeyValue{
+			{
+				Key:   "host.name",
+				Value: &protobufs.AnyValue{Value: &protobufs.AnyValue_StringValue{StringValue: "somehost"}},
+			},
+		},
+	}
+	err := CalcHashAgentDescription(agentDescr)
+	if err != nil {
+		log.Fatalln(err)
+	}
+	return agentDescr
+}
+
 func testClients(t *testing.T, f func(client OpAMPClient)) {
 	// Run the test defined by f() for WebSocket and HTTP clients.
 	tests := []struct {
@@ -52,7 +68,7 @@ func TestConnectInvalidURL(t *testing.T) {
 			OpAMPServerURL: ":not a url",
 		}
 
-		err := client.Start(settings)
+		err := client.Start(context.Background(), settings)
 		assert.Error(t, err)
 	})
 }
@@ -77,12 +93,12 @@ func prepareClient(t *testing.T, settings *StartSettings, c OpAMPClient) {
 	}
 	settings.OpAMPServerURL = u.String()
 
-	settings.AgentDescription = &protobufs.AgentDescription{}
+	settings.AgentDescription = createAgentDescr()
 }
 
 func startClient(t *testing.T, settings StartSettings, client OpAMPClient) {
 	prepareClient(t, &settings, client)
-	err := client.Start(settings)
+	err := client.Start(context.Background(), settings)
 	assert.NoError(t, err)
 }
 
@@ -126,7 +142,7 @@ func TestStartStarted(t *testing.T) {
 		startClient(t, settings, client)
 
 		// Try to start again.
-		err := client.Start(settings)
+		err := client.Start(context.Background(), settings)
 		assert.Error(t, err)
 
 		err = client.Stop(context.Background())
@@ -221,7 +237,7 @@ func TestConnectWithServer503(t *testing.T) {
 
 		// Shutdown the server.
 		srv.Close()
-		client.Stop(context.Background())
+		_ = client.Stop(context.Background())
 	})
 }
 
@@ -248,7 +264,7 @@ func TestConnectWithHeader(t *testing.T) {
 
 		// Shutdown the server and the client.
 		srv.Close()
-		client.Stop(context.Background())
+		_ = client.Stop(context.Background())
 	})
 }
 
@@ -362,6 +378,18 @@ func TestIncludesDetailsOnReconnect(t *testing.T) {
 	assert.NoError(t, err)
 }
 
+func createEffectiveConfig() *protobufs.EffectiveConfig {
+	cfg := &protobufs.EffectiveConfig{
+		ConfigMap: &protobufs.AgentConfigMap{
+			ConfigMap: map[string]*protobufs.AgentConfigFile{
+				"key": {},
+			},
+		},
+	}
+	CalcHashEffectiveConfig(cfg)
+	return cfg
+}
+
 func TestSetEffectiveConfig(t *testing.T) {
 	testClients(t, func(client OpAMPClient) {
 		// Start a server.
@@ -377,24 +405,20 @@ func TestSetEffectiveConfig(t *testing.T) {
 		}
 
 		// Start a client.
-		settings := StartSettings{}
-		settings.OpAMPServerURL = "ws://" + srv.Endpoint
-		prepareClient(t, &settings, client)
-
-		sendConfig := &protobufs.EffectiveConfig{
-			ConfigMap: &protobufs.AgentConfigMap{
-				ConfigMap: map[string]*protobufs.AgentConfigFile{
-					"key": {},
+		sendConfig := createEffectiveConfig()
+		settings := StartSettings{
+			Callbacks: types.CallbacksStruct{
+				GetEffectiveConfigFunc: func(ctx context.Context) (*protobufs.EffectiveConfig, error) {
+					return sendConfig, nil
 				},
 			},
 		}
+		settings.OpAMPServerURL = "ws://" + srv.Endpoint
+		prepareClient(t, &settings, client)
 
-		// Set before start. This should be delivered immediately after Start().
-		client.SetEffectiveConfig(sendConfig)
-
-		assert.NoError(t, client.Start(settings))
+		assert.NoError(t, client.Start(context.Background(), settings))
 
-		// Verify it is delivered.
+		// Verify config is delivered.
 		eventually(
 			t,
 			func() bool {
@@ -403,9 +427,9 @@ func TestSetEffectiveConfig(t *testing.T) {
 			},
 		)
 
-		// Now change again.
+		// Now change the config.
 		sendConfig.ConfigMap.ConfigMap["key2"] = &protobufs.AgentConfigFile{}
-		client.SetEffectiveConfig(sendConfig)
+		_ = client.UpdateEffectiveConfig(context.Background())
 
 		// Verify change is delivered.
 		eventually(
@@ -426,22 +450,7 @@ func TestSetEffectiveConfig(t *testing.T) {
 	})
 }
 
-func isEqualAgentAttrs(sent []*protobufs.KeyValue, received []*protobufs.KeyValue) bool {
-	if len(sent) != len(received) {
-		return false
-	}
-
-	for i, rval := range received {
-		sval := sent[i]
-		if !protobufshelpers.IsEqualKeyValue(rval, sval) {
-			return false
-		}
-	}
-
-	return true
-}
-
-func TestSetAgentAttributes(t *testing.T) {
+func TestSetAgentDescription(t *testing.T) {
 	testClients(t, func(client OpAMPClient) {
 
 		// Start a server.
@@ -462,17 +471,10 @@ func TestSetAgentAttributes(t *testing.T) {
 		}
 		prepareClient(t, &settings, client)
 
-		agentDescr := &protobufs.AgentDescription{
-			IdentifyingAttributes: []*protobufs.KeyValue{
-				{
-					Key:   "host.name",
-					Value: &protobufs.AnyValue{Value: &protobufs.AnyValue_StringValue{StringValue: "somehost"}},
-				},
-			},
-		}
-		client.SetAgentDescription(agentDescr)
+		clientAgentDescr := createAgentDescr()
+		assert.NoError(t, client.SetAgentDescription(clientAgentDescr))
 
-		assert.NoError(t, client.Start(settings))
+		assert.NoError(t, client.Start(context.Background(), settings))
 
 		// Verify it is delivered.
 		eventually(
@@ -482,21 +484,19 @@ func TestSetAgentAttributes(t *testing.T) {
 				if !ok || agentDescr == nil {
 					return false
 				}
-				return isEqualAgentAttrs(
-					agentDescr.IdentifyingAttributes, agentDescr.IdentifyingAttributes,
-				)
+				return proto.Equal(clientAgentDescr, agentDescr)
 			},
 		)
 
 		// Now change again.
-		agentDescr.NonIdentifyingAttributes = []*protobufs.KeyValue{
+		clientAgentDescr.NonIdentifyingAttributes = []*protobufs.KeyValue{
 			{
 				Key:   "os.name",
 				Value: &protobufs.AnyValue{Value: &protobufs.AnyValue_StringValue{StringValue: "linux"}},
 			},
 		}
-
-		client.SetAgentDescription(agentDescr)
+		assert.NoError(t, CalcHashAgentDescription(clientAgentDescr))
+		assert.NoError(t, client.SetAgentDescription(clientAgentDescr))
 
 		// Verify change is delivered.
 		eventually(
@@ -506,8 +506,7 @@ func TestSetAgentAttributes(t *testing.T) {
 				if agentDescr == nil {
 					return false
 				}
-				return isEqualAgentAttrs(agentDescr.IdentifyingAttributes, agentDescr.IdentifyingAttributes) &&
-					isEqualAgentAttrs(agentDescr.NonIdentifyingAttributes, agentDescr.NonIdentifyingAttributes)
+				return proto.Equal(clientAgentDescr, agentDescr)
 			},
 		)
 
@@ -517,7 +516,6 @@ func TestSetAgentAttributes(t *testing.T) {
 		// Shutdown the client.
 		err := client.Stop(context.Background())
 		assert.NoError(t, err)
-
 	})
 }
 
@@ -542,7 +540,7 @@ func TestAgentIdentification(t *testing.T) {
 		// Start a client.
 		settings := StartSettings{}
 		settings.OpAMPServerURL = "ws://" + srv.Endpoint
-		settings.AgentDescription = &protobufs.AgentDescription{}
+		settings.AgentDescription = createAgentDescr()
 		settings.Callbacks = types.CallbacksStruct{
 			OnAgentIdentificationFunc: func(
 				ctx context.Context,
@@ -554,7 +552,7 @@ func TestAgentIdentification(t *testing.T) {
 		prepareClient(t, &settings, client)
 
 		oldInstanceUid := settings.InstanceUid
-		assert.NoError(t, client.Start(settings))
+		assert.NoError(t, client.Start(context.Background(), settings))
 
 		// First, server gets the original instanceId
 		eventually(
@@ -569,7 +567,7 @@ func TestAgentIdentification(t *testing.T) {
 		)
 
 		// Send a dummy message
-		client.SetAgentDescription(&protobufs.AgentDescription{})
+		_ = client.SetAgentDescription(createAgentDescr())
 
 		// When it was sent, the new instance uid should have been used, which should
 		// have been observed by the server
@@ -670,7 +668,7 @@ func TestConnectionSettings(t *testing.T) {
 		settings.OpAMPServerURL = "ws://" + srv.Endpoint
 		prepareClient(t, &settings, client)
 
-		assert.NoError(t, client.Start(settings))
+		assert.NoError(t, client.Start(context.Background(), settings))
 
 		eventually(t, func() bool { return atomic.LoadInt64(&gotOpampSettings) == 1 })
 		eventually(t, func() bool { return atomic.LoadInt64(&gotOwnSettings) == 3 })
@@ -685,3 +683,136 @@ func TestConnectionSettings(t *testing.T) {
 		assert.NoError(t, err)
 	})
 }
+
+func TestReportAgentDescription(t *testing.T) {
+	testClients(t, func(client OpAMPClient) {
+
+		// Start a server.
+		srv := internal.StartMockServer(t)
+		srv.EnableExpectMode()
+
+		// Start a client.
+		settings := StartSettings{
+			OpAMPServerURL: "ws://" + srv.Endpoint,
+		}
+		prepareClient(t, &settings, client)
+
+		// client --->
+		assert.NoError(t, client.Start(context.Background(), settings))
+
+		// ---> server
+		srv.Expect(func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent {
+			// The first status report after Start must have full AgentDescription.
+			assert.True(t, proto.Equal(settings.AgentDescription, msg.StatusReport.AgentDescription))
+			return &protobufs.ServerToAgent{InstanceUid: msg.InstanceUid}
+		})
+
+		// client --->
+		// Trigger a status report.
+		_ = client.UpdateEffectiveConfig(context.Background())
+
+		// ---> server
+		srv.Expect(func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent {
+			// The status report must have compressed AgentDescription.
+			descr := msg.StatusReport.AgentDescription
+			assert.Nil(t, descr.IdentifyingAttributes)
+			assert.Nil(t, descr.NonIdentifyingAttributes)
+
+			// The Hash field must be present and unchanged.
+			assert.NotNil(t, descr.Hash)
+			assert.EqualValues(t, settings.AgentDescription.Hash, descr.Hash)
+
+			// Ask client for full AgentDescription.
+			return &protobufs.ServerToAgent{
+				InstanceUid: msg.InstanceUid,
+				Flags:       protobufs.ServerToAgent_ReportAgentDescription,
+			}
+		})
+
+		// Server has requested the client to report, so there will be another message
+		// coming to the Server.
+		// ---> server
+		srv.Expect(func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent {
+			// The status report must again have full AgentDescription
+			// because the server asked for it.
+			assert.True(t, proto.Equal(settings.AgentDescription, msg.StatusReport.AgentDescription))
+			return &protobufs.ServerToAgent{InstanceUid: msg.InstanceUid}
+		})
+
+		// Shutdown the server.
+		srv.Close()
+
+		// Shutdown the client.
+		err := client.Stop(context.Background())
+		assert.NoError(t, err)
+	})
+}
+
+func TestReportEffectiveConfig(t *testing.T) {
+	testClients(t, func(client OpAMPClient) {
+
+		// Start a server.
+		srv := internal.StartMockServer(t)
+		srv.EnableExpectMode()
+
+		clientEffectiveConfig := createEffectiveConfig()
+
+		// Start a client.
+		settings := StartSettings{
+			OpAMPServerURL: "ws://" + srv.Endpoint,
+			Callbacks: types.CallbacksStruct{
+				GetEffectiveConfigFunc: func(ctx context.Context) (*protobufs.EffectiveConfig, error) {
+					return clientEffectiveConfig, nil
+				},
+			},
+		}
+		prepareClient(t, &settings, client)
+
+		// client --->
+		assert.NoError(t, client.Start(context.Background(), settings))
+
+		// ---> server
+		srv.Expect(func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent {
+			// The first status report after Start must have full EffectiveConfig.
+			assert.True(t, proto.Equal(clientEffectiveConfig, msg.StatusReport.EffectiveConfig))
+			return &protobufs.ServerToAgent{InstanceUid: msg.InstanceUid}
+		})
+
+		// client --->
+		// Trigger another status report for example by setting AgentDescription.
+		_ = client.SetAgentDescription(settings.AgentDescription)
+
+		// ---> server
+		srv.Expect(func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent {
+			// The status report must have compressed EffectiveConfig.
+			cfg := msg.StatusReport.EffectiveConfig
+			assert.Nil(t, cfg.ConfigMap)
+
+			// Hash must be present and unchanged.
+			assert.NotNil(t, cfg.Hash)
+			assert.EqualValues(t, clientEffectiveConfig.Hash, cfg.Hash)
+
+			// Ask client for full AgentDescription.
+			return &protobufs.ServerToAgent{
+				InstanceUid: msg.InstanceUid,
+				Flags:       protobufs.ServerToAgent_ReportEffectiveConfig,
+			}
+		})
+
+		// Server has requested the client to report, so there will be another message.
+		// ---> server
+		srv.Expect(func(msg *protobufs.AgentToServer) *protobufs.ServerToAgent {
+			// The status report must again have full EffectiveConfig
+			// because server asked for it.
+			assert.True(t, proto.Equal(clientEffectiveConfig, msg.StatusReport.EffectiveConfig))
+			return &protobufs.ServerToAgent{InstanceUid: msg.InstanceUid}
+		})
+
+		// Shutdown the server.
+		srv.Close()
+
+		// Shutdown the client.
+		err := client.Stop(context.Background())
+		assert.NoError(t, err)
+	})
+}
diff --git a/client/httpclient_test.go b/client/httpclient_test.go
index d49d36b..d0093b4 100644
--- a/client/httpclient_test.go
+++ b/client/httpclient_test.go
@@ -31,7 +31,7 @@ func TestHTTPPolling(t *testing.T) {
 	// Shorten the polling interval to speed up the test.
 	client.looper.SetPollingInterval(time.Millisecond * 10)
 
-	assert.NoError(t, client.Start(settings))
+	assert.NoError(t, client.Start(context.Background(), settings))
 
 	// Verify that status report is delivered.
 	eventually(t, func() bool { return atomic.LoadInt64(&rcvCounter) == 1 })
diff --git a/client/internal/wsreceiver_test.go b/client/internal/wsreceiver_test.go
index 24ccd4e..05f390f 100644
--- a/client/internal/wsreceiver_test.go
+++ b/client/internal/wsreceiver_test.go
@@ -71,7 +71,8 @@ func TestServerToAgentCommand(t *testing.T) {
 					return nil
 				},
 			}
-			receiver := NewWSReceiver(TestLogger{t}, callbacks, nil, nil)
+			clientSyncedState := ClientSyncedState{}
+			receiver := NewWSReceiver(TestLogger{t}, callbacks, nil, nil, &clientSyncedState)
 			receiver.processor.ProcessReceivedMessage(context.Background(), &protobufs.ServerToAgent{
 				Command: test.command,
 			})
@@ -94,7 +95,8 @@ func TestServerToAgentCommandExclusive(t *testing.T) {
 			return nil, false, nil
 		},
 	}
-	receiver := NewWSReceiver(TestLogger{t}, callbacks, nil, nil)
+	clientSyncedState := ClientSyncedState{}
+	receiver := NewWSReceiver(TestLogger{t}, callbacks, nil, nil, &clientSyncedState)
 	receiver.processor.ProcessReceivedMessage(context.Background(), &protobufs.ServerToAgent{
 		Command: &protobufs.ServerToAgentCommand{
 			Type: protobufs.ServerToAgentCommand_Restart,
@@ -116,7 +118,8 @@ func TestOnRemoteConfigReportsError(t *testing.T) {
 	}
 
 	sender := NewSender(TestLogger{t})
-	receiver := NewWSReceiver(TestLogger{t}, callbacks, nil, sender)
+	clientSyncedState := ClientSyncedState{}
+	receiver := NewWSReceiver(TestLogger{t}, callbacks, nil, sender, &clientSyncedState)
 
 	receiver.processor.ProcessReceivedMessage(context.Background(), &protobufs.ServerToAgent{
 		RemoteConfig: &protobufs.AgentRemoteConfig{},