diff --git a/.gitlab/ci/.test.yml b/.gitlab/ci/.test.yml
index b494223a2b8104d7d37b9ba316348f815f633375..60fea0a976322b297da439ccb425fd3acebd8336 100644
--- a/.gitlab/ci/.test.yml
+++ b/.gitlab/ci/.test.yml
@@ -18,6 +18,7 @@ unit-test:
         - cd controller
         - make ci-unit-test
     after_script:
+        - cd controller
         - go tool cover -func=coverage.out
     <<: *test
 
diff --git a/.golangci.yml b/.golangci.yml
index b5c8fb3a790edcad9b9e73ce5baa9096fd07b0ac..ccc5f10f0bbd17944a52347b87caddd23d446eec 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -5,6 +5,7 @@ run:
     issues-exit-code: 1
     # directories to be ignored by linters
     skip-dirs:
+        - artifacts
         - controller/forks
         - controller/test
         - controller/mocks
diff --git a/api/go/gosdn/core/core.pb.go b/api/go/gosdn/core/core.pb.go
index 562655fc9c3001e2e5992ff509111d1a7c06ea27..fb190ee9c49be4820013ee45119c93a35e119cd5 100644
--- a/api/go/gosdn/core/core.pb.go
+++ b/api/go/gosdn/core/core.pb.go
@@ -71,16 +71,17 @@ func (Status) EnumDescriptor() ([]byte, []int) {
 	return file_gosdn_core_core_proto_rawDescGZIP(), []int{0}
 }
 
-type GetPndListRequest struct {
+type GetPndRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
-func (x *GetPndListRequest) Reset() {
-	*x = GetPndListRequest{}
+func (x *GetPndRequest) Reset() {
+	*x = GetPndRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_gosdn_core_core_proto_msgTypes[0]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -88,13 +89,13 @@ func (x *GetPndListRequest) Reset() {
 	}
 }
 
-func (x *GetPndListRequest) String() string {
+func (x *GetPndRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetPndListRequest) ProtoMessage() {}
+func (*GetPndRequest) ProtoMessage() {}
 
-func (x *GetPndListRequest) ProtoReflect() protoreflect.Message {
+func (x *GetPndRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_core_core_proto_msgTypes[0]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -106,29 +107,36 @@ func (x *GetPndListRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetPndListRequest.ProtoReflect.Descriptor instead.
-func (*GetPndListRequest) Descriptor() ([]byte, []int) {
+// Deprecated: Use GetPndRequest.ProtoReflect.Descriptor instead.
+func (*GetPndRequest) Descriptor() ([]byte, []int) {
 	return file_gosdn_core_core_proto_rawDescGZIP(), []int{0}
 }
 
-func (x *GetPndListRequest) GetTimestamp() int64 {
+func (x *GetPndRequest) GetTimestamp() int64 {
 	if x != nil {
 		return x.Timestamp
 	}
 	return 0
 }
 
-type GetPndRequest struct {
+func (x *GetPndRequest) GetPid() string {
+	if x != nil {
+		return x.Pid
+	}
+	return ""
+}
+
+type GetPndResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       []string `protobuf:"bytes,3,rep,name=pid,proto3" json:"pid,omitempty"`
+	Timestamp int64                       `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pnd       *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
 }
 
-func (x *GetPndRequest) Reset() {
-	*x = GetPndRequest{}
+func (x *GetPndResponse) Reset() {
+	*x = GetPndResponse{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_gosdn_core_core_proto_msgTypes[1]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -136,13 +144,13 @@ func (x *GetPndRequest) Reset() {
 	}
 }
 
-func (x *GetPndRequest) String() string {
+func (x *GetPndResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetPndRequest) ProtoMessage() {}
+func (*GetPndResponse) ProtoMessage() {}
 
-func (x *GetPndRequest) ProtoReflect() protoreflect.Message {
+func (x *GetPndResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_core_core_proto_msgTypes[1]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -154,36 +162,35 @@ func (x *GetPndRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetPndRequest.ProtoReflect.Descriptor instead.
-func (*GetPndRequest) Descriptor() ([]byte, []int) {
+// Deprecated: Use GetPndResponse.ProtoReflect.Descriptor instead.
+func (*GetPndResponse) Descriptor() ([]byte, []int) {
 	return file_gosdn_core_core_proto_rawDescGZIP(), []int{1}
 }
 
-func (x *GetPndRequest) GetTimestamp() int64 {
+func (x *GetPndResponse) GetTimestamp() int64 {
 	if x != nil {
 		return x.Timestamp
 	}
 	return 0
 }
 
-func (x *GetPndRequest) GetPid() []string {
+func (x *GetPndResponse) GetPnd() *pnd.PrincipalNetworkDomain {
 	if x != nil {
-		return x.Pid
+		return x.Pnd
 	}
 	return nil
 }
 
-type GetPndListResponse struct {
+type GetPndListRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Timestamp int64                         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pnd       []*pnd.PrincipalNetworkDomain `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"`
+	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 }
 
-func (x *GetPndListResponse) Reset() {
-	*x = GetPndListResponse{}
+func (x *GetPndListRequest) Reset() {
+	*x = GetPndListRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_gosdn_core_core_proto_msgTypes[2]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -191,13 +198,13 @@ func (x *GetPndListResponse) Reset() {
 	}
 }
 
-func (x *GetPndListResponse) String() string {
+func (x *GetPndListRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetPndListResponse) ProtoMessage() {}
+func (*GetPndListRequest) ProtoMessage() {}
 
-func (x *GetPndListResponse) ProtoReflect() protoreflect.Message {
+func (x *GetPndListRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_core_core_proto_msgTypes[2]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -209,26 +216,19 @@ func (x *GetPndListResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetPndListResponse.ProtoReflect.Descriptor instead.
-func (*GetPndListResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use GetPndListRequest.ProtoReflect.Descriptor instead.
+func (*GetPndListRequest) Descriptor() ([]byte, []int) {
 	return file_gosdn_core_core_proto_rawDescGZIP(), []int{2}
 }
 
-func (x *GetPndListResponse) GetTimestamp() int64 {
+func (x *GetPndListRequest) GetTimestamp() int64 {
 	if x != nil {
 		return x.Timestamp
 	}
 	return 0
 }
 
-func (x *GetPndListResponse) GetPnd() []*pnd.PrincipalNetworkDomain {
-	if x != nil {
-		return x.Pnd
-	}
-	return nil
-}
-
-type GetPndResponse struct {
+type GetPndListResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
@@ -237,8 +237,8 @@ type GetPndResponse struct {
 	Pnd       []*pnd.PrincipalNetworkDomain `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"`
 }
 
-func (x *GetPndResponse) Reset() {
-	*x = GetPndResponse{}
+func (x *GetPndListResponse) Reset() {
+	*x = GetPndListResponse{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_gosdn_core_core_proto_msgTypes[3]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -246,13 +246,13 @@ func (x *GetPndResponse) Reset() {
 	}
 }
 
-func (x *GetPndResponse) String() string {
+func (x *GetPndListResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetPndResponse) ProtoMessage() {}
+func (*GetPndListResponse) ProtoMessage() {}
 
-func (x *GetPndResponse) ProtoReflect() protoreflect.Message {
+func (x *GetPndListResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_core_core_proto_msgTypes[3]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -264,19 +264,19 @@ func (x *GetPndResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetPndResponse.ProtoReflect.Descriptor instead.
-func (*GetPndResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use GetPndListResponse.ProtoReflect.Descriptor instead.
+func (*GetPndListResponse) Descriptor() ([]byte, []int) {
 	return file_gosdn_core_core_proto_rawDescGZIP(), []int{3}
 }
 
-func (x *GetPndResponse) GetTimestamp() int64 {
+func (x *GetPndListResponse) GetTimestamp() int64 {
 	if x != nil {
 		return x.Timestamp
 	}
 	return 0
 }
 
-func (x *GetPndResponse) GetPnd() []*pnd.PrincipalNetworkDomain {
+func (x *GetPndListResponse) GetPnd() []*pnd.PrincipalNetworkDomain {
 	if x != nil {
 		return x.Pnd
 	}
@@ -574,21 +574,21 @@ var file_gosdn_core_core_proto_rawDesc = []byte{
 	0x6f, 0x72, 0x65, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f,
 	0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
 	0x6f, 0x1a, 0x13, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x2f, 0x70, 0x6e, 0x64,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x31, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64,
-	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
-	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3f, 0x0a, 0x0d, 0x47, 0x65, 0x74,
-	0x50, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
-	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18,
-	0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x67, 0x0a, 0x12, 0x47, 0x65,
-	0x74, 0x50, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33,
-	0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f,
-	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
-	0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03,
-	0x70, 0x6e, 0x64, 0x22, 0x63, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, 0x52, 0x65, 0x73,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
+	0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
+	0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x63, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x6e,
+	0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69,
+	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33, 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
+	0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
+	0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x70, 0x6e, 0x64, 0x22, 0x31, 0x0a, 0x11,
+	0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22,
+	0x67, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
 	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
 	0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
 	0x61, 0x6d, 0x70, 0x12, 0x33, 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
@@ -674,10 +674,10 @@ var file_gosdn_core_core_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
 var file_gosdn_core_core_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
 var file_gosdn_core_core_proto_goTypes = []interface{}{
 	(Status)(0),                        // 0: gosdn.core.Status
-	(*GetPndListRequest)(nil),          // 1: gosdn.core.GetPndListRequest
-	(*GetPndRequest)(nil),              // 2: gosdn.core.GetPndRequest
-	(*GetPndListResponse)(nil),         // 3: gosdn.core.GetPndListResponse
-	(*GetPndResponse)(nil),             // 4: gosdn.core.GetPndResponse
+	(*GetPndRequest)(nil),              // 1: gosdn.core.GetPndRequest
+	(*GetPndResponse)(nil),             // 2: gosdn.core.GetPndResponse
+	(*GetPndListRequest)(nil),          // 3: gosdn.core.GetPndListRequest
+	(*GetPndListResponse)(nil),         // 4: gosdn.core.GetPndListResponse
 	(*CreatePndListRequest)(nil),       // 5: gosdn.core.CreatePndListRequest
 	(*PndCreateProperties)(nil),        // 6: gosdn.core.PndCreateProperties
 	(*CreatePndListResponse)(nil),      // 7: gosdn.core.CreatePndListResponse
@@ -686,17 +686,17 @@ var file_gosdn_core_core_proto_goTypes = []interface{}{
 	(*pnd.PrincipalNetworkDomain)(nil), // 10: gosdn.pnd.PrincipalNetworkDomain
 }
 var file_gosdn_core_core_proto_depIdxs = []int32{
-	10, // 0: gosdn.core.GetPndListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	10, // 1: gosdn.core.GetPndResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	10, // 0: gosdn.core.GetPndResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	10, // 1: gosdn.core.GetPndListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
 	6,  // 2: gosdn.core.CreatePndListRequest.pnd:type_name -> gosdn.core.PndCreateProperties
 	0,  // 3: gosdn.core.CreatePndListResponse.status:type_name -> gosdn.core.Status
 	0,  // 4: gosdn.core.DeletePndResponse.status:type_name -> gosdn.core.Status
-	2,  // 5: gosdn.core.CoreService.GetPnd:input_type -> gosdn.core.GetPndRequest
-	1,  // 6: gosdn.core.CoreService.GetPndList:input_type -> gosdn.core.GetPndListRequest
+	1,  // 5: gosdn.core.CoreService.GetPnd:input_type -> gosdn.core.GetPndRequest
+	3,  // 6: gosdn.core.CoreService.GetPndList:input_type -> gosdn.core.GetPndListRequest
 	5,  // 7: gosdn.core.CoreService.CreatePndList:input_type -> gosdn.core.CreatePndListRequest
 	8,  // 8: gosdn.core.CoreService.DeletePnd:input_type -> gosdn.core.DeletePndRequest
-	4,  // 9: gosdn.core.CoreService.GetPnd:output_type -> gosdn.core.GetPndResponse
-	3,  // 10: gosdn.core.CoreService.GetPndList:output_type -> gosdn.core.GetPndListResponse
+	2,  // 9: gosdn.core.CoreService.GetPnd:output_type -> gosdn.core.GetPndResponse
+	4,  // 10: gosdn.core.CoreService.GetPndList:output_type -> gosdn.core.GetPndListResponse
 	7,  // 11: gosdn.core.CoreService.CreatePndList:output_type -> gosdn.core.CreatePndListResponse
 	9,  // 12: gosdn.core.CoreService.DeletePnd:output_type -> gosdn.core.DeletePndResponse
 	9,  // [9:13] is the sub-list for method output_type
@@ -713,7 +713,7 @@ func file_gosdn_core_core_proto_init() {
 	}
 	if !protoimpl.UnsafeEnabled {
 		file_gosdn_core_core_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetPndListRequest); i {
+			switch v := v.(*GetPndRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -725,7 +725,7 @@ func file_gosdn_core_core_proto_init() {
 			}
 		}
 		file_gosdn_core_core_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetPndRequest); i {
+			switch v := v.(*GetPndResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -737,7 +737,7 @@ func file_gosdn_core_core_proto_init() {
 			}
 		}
 		file_gosdn_core_core_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetPndListResponse); i {
+			switch v := v.(*GetPndListRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -749,7 +749,7 @@ func file_gosdn_core_core_proto_init() {
 			}
 		}
 		file_gosdn_core_core_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetPndResponse); i {
+			switch v := v.(*GetPndListResponse); i {
 			case 0:
 				return &v.state
 			case 1:
diff --git a/api/go/gosdn/core/core.pb.gw.go b/api/go/gosdn/core/core.pb.gw.go
index f20b6b3fcf07850e55869757651a55ebdeccda38..8c56242b632551449573f8c7e56c895e2fe3c12f 100644
--- a/api/go/gosdn/core/core.pb.gw.go
+++ b/api/go/gosdn/core/core.pb.gw.go
@@ -51,7 +51,7 @@ func request_CoreService_GetPnd_0(ctx context.Context, marshaler runtime.Marshal
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
 
-	protoReq.Pid, err = runtime.StringSlice(val, ",")
+	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
@@ -84,7 +84,7 @@ func local_request_CoreService_GetPnd_0(ctx context.Context, marshaler runtime.M
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
 
-	protoReq.Pid, err = runtime.StringSlice(val, ",")
+	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
diff --git a/api/go/gosdn/pnd/pnd.pb.go b/api/go/gosdn/pnd/pnd.pb.go
index 3738f74a09fbca7fb2ffe3c9e2116e6e3606bf44..8b52d80fe24ce2736647ae104ff754eaa8be9562 100644
--- a/api/go/gosdn/pnd/pnd.pb.go
+++ b/api/go/gosdn/pnd/pnd.pb.go
@@ -292,7 +292,7 @@ type GetOndListRequest struct {
 	unknownFields protoimpl.UnknownFields
 
 	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
 func (x *GetOndListRequest) Reset() {
@@ -346,9 +346,9 @@ type GetOndRequest struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Did       []string `protobuf:"bytes,3,rep,name=did,proto3" json:"did,omitempty"`
-	Pid       string   `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Did       string `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"`
+	Pid       string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
 func (x *GetOndRequest) Reset() {
@@ -390,11 +390,11 @@ func (x *GetOndRequest) GetTimestamp() int64 {
 	return 0
 }
 
-func (x *GetOndRequest) GetDid() []string {
+func (x *GetOndRequest) GetDid() string {
 	if x != nil {
 		return x.Did
 	}
-	return nil
+	return ""
 }
 
 func (x *GetOndRequest) GetPid() string {
@@ -410,7 +410,7 @@ type GetSbiListRequest struct {
 	unknownFields protoimpl.UnknownFields
 
 	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
 func (x *GetSbiListRequest) Reset() {
@@ -464,9 +464,9 @@ type GetSbiRequest struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Sid       []string `protobuf:"bytes,3,rep,name=sid,proto3" json:"sid,omitempty"`
-	Pid       string   `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Sid       string `protobuf:"bytes,2,opt,name=sid,proto3" json:"sid,omitempty"`
+	Pid       string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
 func (x *GetSbiRequest) Reset() {
@@ -508,11 +508,11 @@ func (x *GetSbiRequest) GetTimestamp() int64 {
 	return 0
 }
 
-func (x *GetSbiRequest) GetSid() []string {
+func (x *GetSbiRequest) GetSid() string {
 	if x != nil {
 		return x.Sid
 	}
-	return nil
+	return ""
 }
 
 func (x *GetSbiRequest) GetPid() string {
@@ -528,7 +528,7 @@ type GetChangeListRequest struct {
 	unknownFields protoimpl.UnknownFields
 
 	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
 func (x *GetChangeListRequest) Reset() {
@@ -582,9 +582,9 @@ type GetChangeRequest struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Cuid      string `protobuf:"bytes,3,opt,name=cuid,proto3" json:"cuid,omitempty"`
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Cuid      []string `protobuf:"bytes,2,rep,name=cuid,proto3" json:"cuid,omitempty"`
+	Pid       string   `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 }
 
 func (x *GetChangeRequest) Reset() {
@@ -626,11 +626,11 @@ func (x *GetChangeRequest) GetTimestamp() int64 {
 	return 0
 }
 
-func (x *GetChangeRequest) GetCuid() string {
+func (x *GetChangeRequest) GetCuid() []string {
 	if x != nil {
 		return x.Cuid
 	}
-	return ""
+	return nil
 }
 
 func (x *GetChangeRequest) GetPid() string {
@@ -719,8 +719,8 @@ type GetOndResponse struct {
 	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd *PrincipalNetworkDomain         `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Ond []*OrchestratedNetworkingDevice `protobuf:"bytes,3,rep,name=ond,proto3" json:"ond,omitempty"`
+	Pnd *PrincipalNetworkDomain       `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Ond *OrchestratedNetworkingDevice `protobuf:"bytes,3,opt,name=ond,proto3" json:"ond,omitempty"`
 }
 
 func (x *GetOndResponse) Reset() {
@@ -769,7 +769,7 @@ func (x *GetOndResponse) GetPnd() *PrincipalNetworkDomain {
 	return nil
 }
 
-func (x *GetOndResponse) GetOnd() []*OrchestratedNetworkingDevice {
+func (x *GetOndResponse) GetOnd() *OrchestratedNetworkingDevice {
 	if x != nil {
 		return x.Ond
 	}
@@ -849,8 +849,8 @@ type GetSbiResponse struct {
 	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd *PrincipalNetworkDomain           `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Sbi []*southbound.SouthboundInterface `protobuf:"bytes,3,rep,name=sbi,proto3" json:"sbi,omitempty"`
+	Pnd *PrincipalNetworkDomain         `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Sbi *southbound.SouthboundInterface `protobuf:"bytes,3,opt,name=sbi,proto3" json:"sbi,omitempty"`
 }
 
 func (x *GetSbiResponse) Reset() {
@@ -899,7 +899,7 @@ func (x *GetSbiResponse) GetPnd() *PrincipalNetworkDomain {
 	return nil
 }
 
-func (x *GetSbiResponse) GetSbi() []*southbound.SouthboundInterface {
+func (x *GetSbiResponse) GetSbi() *southbound.SouthboundInterface {
 	if x != nil {
 		return x.Sbi
 	}
@@ -1305,9 +1305,10 @@ type Change struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Id    string      `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Age   int64       `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
-	State ChangeState `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.pnd.ChangeState" json:"state,omitempty"`
+	Id    string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Age   int64              `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
+	State ChangeState        `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.pnd.ChangeState" json:"state,omitempty"`
+	Diff  *gnmi.Notification `protobuf:"bytes,4,opt,name=diff,proto3" json:"diff,omitempty"`
 }
 
 func (x *Change) Reset() {
@@ -1363,6 +1364,13 @@ func (x *Change) GetState() ChangeState {
 	return ChangeState_CHANGE_STATE_UNSPECIFIED
 }
 
+func (x *Change) GetDiff() *gnmi.Notification {
+	if x != nil {
+		return x.Diff
+	}
+	return nil
+}
+
 type SetOndListRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1866,7 +1874,8 @@ type SetResponse struct {
 	unknownFields protoimpl.UnknownFields
 
 	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Status    Status `protobuf:"varint,2,opt,name=status,proto3,enum=gosdn.pnd.Status" json:"status,omitempty"`
+	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	Status    Status `protobuf:"varint,3,opt,name=status,proto3,enum=gosdn.pnd.Status" json:"status,omitempty"`
 }
 
 func (x *SetResponse) Reset() {
@@ -1908,6 +1917,13 @@ func (x *SetResponse) GetTimestamp() int64 {
 	return 0
 }
 
+func (x *SetResponse) GetId() string {
+	if x != nil {
+		return x.Id
+	}
+	return ""
+}
+
 func (x *SetResponse) GetStatus() Status {
 	if x != nil {
 		return x.Status
@@ -2228,8 +2244,8 @@ type DeleteOndRequest struct {
 	unknownFields protoimpl.UnknownFields
 
 	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
-	Did       string `protobuf:"bytes,5,opt,name=did,proto3" json:"did,omitempty"`
+	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	Did       string `protobuf:"bytes,3,opt,name=did,proto3" json:"did,omitempty"`
 }
 
 func (x *DeleteOndRequest) Reset() {
@@ -2363,31 +2379,31 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74,
 	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
 	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x0d, 0x47,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x0d, 0x47,
 	0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
 	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
 	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69,
-	0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03,
-	0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x43,
+	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03,
+	0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x43,
 	0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
 	0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
 	0x70, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x71,
 	0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
 	0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
-	0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x03, 0x73, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x73, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
 	0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x46, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61,
 	0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
 	0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
 	0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03,
-	0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x56,
+	0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x56,
 	0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
 	0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
 	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-	0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-	0x63, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04,
+	0x63, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
 	0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x66, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74,
 	0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
 	0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d,
@@ -2401,7 +2417,7 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x33, 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67,
 	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70,
 	0x61, 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
-	0x03, 0x70, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x03, 0x6f, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28,
+	0x03, 0x70, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x03, 0x6f, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
 	0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x4f, 0x72,
 	0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
 	0x6b, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x03, 0x6f, 0x6e, 0x64, 0x22,
@@ -2422,7 +2438,7 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x50,
 	0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44,
 	0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x70, 0x6e, 0x64, 0x12, 0x37, 0x0a, 0x03, 0x73, 0x62,
-	0x69, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
 	0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, 0x75, 0x74, 0x68,
 	0x62, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x03,
 	0x73, 0x62, 0x69, 0x22, 0xa0, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69,
@@ -2480,85 +2496,79 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74,
 	0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e,
 	0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x22,
-	0x58, 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x73,
-	0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61,
-	0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x74,
-	0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
+	0x80, 0x01, 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x05,
+	0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74,
+	0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x64, 0x69,
+	0x66, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e,
+	0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x64, 0x69,
+	0x66, 0x66, 0x22, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
+	0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
+	0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x03, 0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
+	0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x03, 0x6f, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69,
+	0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x11,
+	0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
+	0x23, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67,
+	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52,
+	0x03, 0x73, 0x62, 0x69, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x74, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61,
+	0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
 	0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x03,
-	0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x03, 0x6f, 0x6e,
-	0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x70, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73,
-	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
-	0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d,
-	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
-	0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, 0x10, 0x0a, 0x03, 0x70,
-	0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x74, 0x0a,
-	0x14, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
-	0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
-	0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
-	0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67,
-	0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x70, 0x69, 0x64, 0x22, 0x85, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c,
-	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
-	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e,
-	0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61,
-	0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e,
-	0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x7b, 0x0a, 0x0d, 0x43,
-	0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03,
-	0x64, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x12,
-	0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61,
-	0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x70, 0x69, 0x5f,
-	0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x52, 0x05, 0x61, 0x70, 0x69, 0x4f, 0x70, 0x22, 0xc9, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x74,
-	0x4f, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a,
-	0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f,
-	0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63,
-	0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
-	0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76,
-	0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73,
-	0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
-	0x6f, 0x72, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74,
-	0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70,
-	0x74, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a, 0x06, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x2d,
-	0x0a, 0x08, 0x73, 0x62, 0x69, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
-	0x32, 0x12, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x62, 0x69,
-	0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x73, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x22, 0x45, 0x0a,
-	0x09, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x75,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x75, 0x69, 0x64, 0x12, 0x24,
-	0x0a, 0x02, 0x6f, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x52, 0x02, 0x6f, 0x70, 0x22, 0x56, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74,
-	0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a,
-	0x12, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+	0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x06,
+	0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67,
+	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e,
+	0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69,
+	0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x85, 0x01, 0x0a,
+	0x12, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74,
-	0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x09,
-	0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
+	0x70, 0x12, 0x3f, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64,
+	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x70, 0x69, 0x64, 0x22, 0x7b, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x70, 0x69, 0x5f, 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x0e, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x41, 0x70,
+	0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x61, 0x70, 0x69, 0x4f,
+	0x70, 0x22, 0xc9, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61,
+	0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74,
+	0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e,
+	0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12,
+	0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65,
+	0x12, 0x4b, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x73,
+	0x64, 0x6e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x54, 0x72, 0x61,
+	0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x74, 0x72,
+	0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a,
+	0x06, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x2d, 0x0a, 0x08, 0x73, 0x62, 0x69, 0x5f, 0x74,
+	0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x73, 0x64,
+	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x73,
+	0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61,
+	0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x63, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
+	0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x70, 0x22, 0x66, 0x0a,
+	0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09,
+	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73,
+	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64,
 	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09,
 	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
 	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74,
@@ -2567,14 +2577,33 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
 	0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
 	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x11, 0x53,
-	0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29,
-	0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11,
-	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75,
-	0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x65,
-	0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15,
+	0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+	0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
+	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34,
+	0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65,
+	0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67,
+	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69,
+	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73,
+	0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69,
+	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18,
+	0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
+	0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74,
+	0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
 	0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20,
 	0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29,
 	0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11,
@@ -2583,162 +2612,153 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67,
 	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70,
 	0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22,
-	0x94, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
-	0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
-	0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
-	0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
-	0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
-	0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
+	0x54, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+	0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x03, 0x64, 0x69, 0x64, 0x22, 0x5c, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f,
+	0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
 	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18,
-	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69,
-	0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x22, 0x5c, 0x0a, 0x11,
-	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
-	0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
-	0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74,
-	0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x9c, 0x01, 0x0a, 0x0b, 0x43,
-	0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48,
-	0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
-	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x48, 0x41, 0x4e,
-	0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47,
-	0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41,
-	0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1a,
-	0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43,
-	0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48,
-	0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4e,
-	0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x04, 0x2a, 0x7c, 0x0a, 0x0c, 0x41, 0x70, 0x69,
-	0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x50, 0x49,
-	0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
-	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f,
-	0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45,
-	0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54,
-	0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a,
-	0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44,
-	0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x07, 0x53, 0x62, 0x69, 0x54, 0x79,
-	0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55,
-	0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13,
-	0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4f, 0x4e,
-	0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50,
-	0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x49, 0x53, 0x45, 0x44, 0x10,
-	0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c,
-	0x55, 0x47, 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e,
-	0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14,
-	0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41,
-	0x54, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f,
-	0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50,
-	0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x10,
-	0x03, 0x2a, 0x41, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53,
-	0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
-	0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b,
-	0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52,
-	0x4f, 0x52, 0x10, 0x02, 0x32, 0xfc, 0x09, 0x0a, 0x0a, 0x50, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73,
-	0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65,
-	0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f,
-	0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18,
-	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70,
-	0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x5c, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f,
-	0x6e, 0x64, 0x12, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47,
-	0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12,
-	0x15, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64,
-	0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64,
-	0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
-	0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
-	0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70,
-	0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x63,
-	0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c,
-	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73,
-	0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02,
-	0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73,
-	0x62, 0x69, 0x73, 0x12, 0x5d, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x18, 0x2e,
-	0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
-	0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x70, 0x6e, 0x64,
-	0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x2f, 0x7b, 0x73, 0x69,
-	0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74,
-	0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74,
-	0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d,
-	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62,
-	0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82,
-	0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f,
-	0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x12, 0x6f, 0x0a, 0x0d, 0x47, 0x65,
-	0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f,
-	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67,
-	0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e,
-	0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b,
-	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70,
-	0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47,
-	0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
-	0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x70, 0x6e,
-	0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73,
-	0x2f, 0x7b, 0x63, 0x75, 0x69, 0x64, 0x7d, 0x12, 0x72, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x68,
-	0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69,
-	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c,
-	0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4,
-	0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70,
-	0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x07, 0x47,
-	0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
-	0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65,
-	0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82,
-	0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69,
-	0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61,
-	0x74, 0x68, 0x73, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x7d, 0x12, 0x6f, 0x0a, 0x0b, 0x53, 0x65,
-	0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73,
-	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b,
-	0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d,
-	0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x66, 0x0a, 0x09, 0x44,
-	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
-	0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x70, 0x6e,
-	0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64,
-	0x69, 0x64, 0x7d, 0x42, 0xae, 0x02, 0x5a, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69,
-	0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x92, 0x41, 0xfb, 0x01, 0x12, 0xf8, 0x01, 0x0a, 0x10, 0x67, 0x6f,
-	0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x4d,
-	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20,
-	0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61,
-	0x6e, 0x64, 0x20, 0x47, 0x6f, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
-	0x68, 0x65, 0x20, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f,
-	0x75, 0x6e, 0x64, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3e, 0x0a,
-	0x18, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e,
-	0x64, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73,
-	0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61,
-	0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2a, 0x50, 0x0a,
-	0x14, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69,
-	0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63,
-	0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f,
-	0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x2d, 0x2f, 0x62, 0x6c, 0x6f, 0x62,
-	0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32,
-	0x03, 0x30, 0x2e, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
+	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
+	0x74, 0x75, 0x73, 0x2a, 0x9c, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74,
+	0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54,
+	0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+	0x00, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54,
+	0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43,
+	0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
+	0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47,
+	0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45,
+	0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54,
+	0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4e, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54,
+	0x10, 0x04, 0x2a, 0x7c, 0x0a, 0x0c, 0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54,
+	0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+	0x00, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49,
+	0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41,
+	0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50,
+	0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50,
+	0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03,
+	0x2a, 0x6d, 0x0a, 0x07, 0x53, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53,
+	0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+	0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50,
+	0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1a,
+	0x0a, 0x16, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41,
+	0x49, 0x4e, 0x45, 0x52, 0x49, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x42,
+	0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x03, 0x2a,
+	0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15,
+	0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+	0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41,
+	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a,
+	0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
+	0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e,
+	0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x10, 0x03, 0x2a, 0x41, 0x0a, 0x06, 0x53, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55,
+	0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09,
+	0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53,
+	0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0xfc, 0x09,
+	0x0a, 0x0a, 0x50, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a,
+	0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73,
+	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
+	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12,
+	0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64,
+	0x73, 0x12, 0x5c, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x12, 0x18, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
+	0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f,
+	0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x12,
+	0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e,
+	0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69,
+	0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93,
+	0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69,
+	0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x63, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x62,
+	0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
+	0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
+	0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64,
+	0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x12, 0x5d, 0x0a, 0x06,
+	0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
+	0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74,
+	0x53, 0x62, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4,
+	0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d,
+	0x2f, 0x73, 0x62, 0x69, 0x73, 0x2f, 0x7b, 0x73, 0x69, 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53,
+	0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64,
+	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01,
+	0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73,
+	0x62, 0x69, 0x73, 0x12, 0x6f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
+	0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
+	0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
+	0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12,
+	0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61,
+	0x6e, 0x67, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67,
+	0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65,
+	0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68,
+	0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64,
+	0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x2f, 0x7b, 0x63, 0x75, 0x69, 0x64, 0x7d,
+	0x12, 0x72, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73,
+	0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65,
+	0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
+	0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22,
+	0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61,
+	0x6e, 0x67, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12,
+	0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50,
+	0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73,
+	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23,
+	0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73,
+	0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2f, 0x7b, 0x70, 0x61,
+	0x74, 0x68, 0x7d, 0x12, 0x6f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69,
+	0x73, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
+	0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65,
+	0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x70,
+	0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x70,
+	0x61, 0x74, 0x68, 0x73, 0x12, 0x66, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e,
+	0x64, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65,
+	0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
+	0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64,
+	0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x42, 0xae, 0x02, 0x5a,
+	0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64,
+	0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70,
+	0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x92, 0x41,
+	0xfb, 0x01, 0x12, 0xf8, 0x01, 0x0a, 0x10, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72,
+	0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x4d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
+	0x6c, 0x20, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x20, 0x63,
+	0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x53, 0x44,
+	0x4e, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x49, 0x6e, 0x74,
+	0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3e, 0x0a, 0x18, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20,
+	0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+	0x63, 0x74, 0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65,
+	0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e,
+	0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2a, 0x50, 0x0a, 0x14, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d,
+	0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x38,
+	0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69,
+	0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61,
+	0x70, 0x69, 0x2f, 0x2d, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
+	0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x03, 0x30, 0x2e, 0x31, 0x62, 0x06, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -2816,55 +2836,56 @@ var file_gosdn_pnd_pnd_proto_depIdxs = []int32{
 	39, // 14: gosdn.pnd.OrchestratedNetworkingDevice.device:type_name -> gnmi.Notification
 	38, // 15: gosdn.pnd.OrchestratedNetworkingDevice.sbi:type_name -> gosdn.southbound.SouthboundInterface
 	0,  // 16: gosdn.pnd.Change.state:type_name -> gosdn.pnd.ChangeState
-	27, // 17: gosdn.pnd.SetOndListRequest.ond:type_name -> gosdn.pnd.SetOnd
-	28, // 18: gosdn.pnd.SetSbiListRequest.sbi:type_name -> gosdn.pnd.SetSbi
-	29, // 19: gosdn.pnd.SetChangeListRequest.change:type_name -> gosdn.pnd.SetChange
-	26, // 20: gosdn.pnd.SetPathListRequest.change_request:type_name -> gosdn.pnd.ChangeRequest
-	1,  // 21: gosdn.pnd.ChangeRequest.api_op:type_name -> gosdn.pnd.ApiOperation
-	38, // 22: gosdn.pnd.SetOnd.sbi:type_name -> gosdn.southbound.SouthboundInterface
-	40, // 23: gosdn.pnd.SetOnd.transport_option:type_name -> gosdn.transport.TransportOption
-	2,  // 24: gosdn.pnd.SetSbi.sbi_type:type_name -> gosdn.pnd.SbiType
-	3,  // 25: gosdn.pnd.SetChange.op:type_name -> gosdn.pnd.Operation
-	4,  // 26: gosdn.pnd.SetResponse.status:type_name -> gosdn.pnd.Status
-	4,  // 27: gosdn.pnd.SetOndListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 28: gosdn.pnd.SetOndListResponse.responses:type_name -> gosdn.pnd.SetResponse
-	4,  // 29: gosdn.pnd.SetChangeListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 30: gosdn.pnd.SetChangeListResponse.responses:type_name -> gosdn.pnd.SetResponse
-	4,  // 31: gosdn.pnd.SetChangeResponse.status:type_name -> gosdn.pnd.Status
-	4,  // 32: gosdn.pnd.SetSbiListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 33: gosdn.pnd.SetSbiListResponse.responses:type_name -> gosdn.pnd.SetResponse
-	4,  // 34: gosdn.pnd.SetPathListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 35: gosdn.pnd.SetPathListResponse.responses:type_name -> gosdn.pnd.SetResponse
-	4,  // 36: gosdn.pnd.DeleteOndResponse.status:type_name -> gosdn.pnd.Status
-	5,  // 37: gosdn.pnd.PndService.GetOndList:input_type -> gosdn.pnd.GetOndListRequest
-	6,  // 38: gosdn.pnd.PndService.GetOnd:input_type -> gosdn.pnd.GetOndRequest
-	22, // 39: gosdn.pnd.PndService.SetOndList:input_type -> gosdn.pnd.SetOndListRequest
-	7,  // 40: gosdn.pnd.PndService.GetSbiList:input_type -> gosdn.pnd.GetSbiListRequest
-	8,  // 41: gosdn.pnd.PndService.GetSbi:input_type -> gosdn.pnd.GetSbiRequest
-	23, // 42: gosdn.pnd.PndService.SetSbiList:input_type -> gosdn.pnd.SetSbiListRequest
-	9,  // 43: gosdn.pnd.PndService.GetChangeList:input_type -> gosdn.pnd.GetChangeListRequest
-	10, // 44: gosdn.pnd.PndService.GetChange:input_type -> gosdn.pnd.GetChangeRequest
-	24, // 45: gosdn.pnd.PndService.SetChangeList:input_type -> gosdn.pnd.SetChangeListRequest
-	11, // 46: gosdn.pnd.PndService.GetPath:input_type -> gosdn.pnd.GetPathRequest
-	25, // 47: gosdn.pnd.PndService.SetPathList:input_type -> gosdn.pnd.SetPathListRequest
-	36, // 48: gosdn.pnd.PndService.DeleteOnd:input_type -> gosdn.pnd.DeleteOndRequest
-	13, // 49: gosdn.pnd.PndService.GetOndList:output_type -> gosdn.pnd.GetOndListResponse
-	12, // 50: gosdn.pnd.PndService.GetOnd:output_type -> gosdn.pnd.GetOndResponse
-	31, // 51: gosdn.pnd.PndService.SetOndList:output_type -> gosdn.pnd.SetOndListResponse
-	15, // 52: gosdn.pnd.PndService.GetSbiList:output_type -> gosdn.pnd.GetSbiListResponse
-	14, // 53: gosdn.pnd.PndService.GetSbi:output_type -> gosdn.pnd.GetSbiResponse
-	34, // 54: gosdn.pnd.PndService.SetSbiList:output_type -> gosdn.pnd.SetSbiListResponse
-	18, // 55: gosdn.pnd.PndService.GetChangeList:output_type -> gosdn.pnd.GetChangeListResponse
-	17, // 56: gosdn.pnd.PndService.GetChange:output_type -> gosdn.pnd.GetChangeResponse
-	32, // 57: gosdn.pnd.PndService.SetChangeList:output_type -> gosdn.pnd.SetChangeListResponse
-	16, // 58: gosdn.pnd.PndService.GetPath:output_type -> gosdn.pnd.GetPathResponse
-	35, // 59: gosdn.pnd.PndService.SetPathList:output_type -> gosdn.pnd.SetPathListResponse
-	37, // 60: gosdn.pnd.PndService.DeleteOnd:output_type -> gosdn.pnd.DeleteOndResponse
-	49, // [49:61] is the sub-list for method output_type
-	37, // [37:49] is the sub-list for method input_type
-	37, // [37:37] is the sub-list for extension type_name
-	37, // [37:37] is the sub-list for extension extendee
-	0,  // [0:37] is the sub-list for field type_name
+	39, // 17: gosdn.pnd.Change.diff:type_name -> gnmi.Notification
+	27, // 18: gosdn.pnd.SetOndListRequest.ond:type_name -> gosdn.pnd.SetOnd
+	28, // 19: gosdn.pnd.SetSbiListRequest.sbi:type_name -> gosdn.pnd.SetSbi
+	29, // 20: gosdn.pnd.SetChangeListRequest.change:type_name -> gosdn.pnd.SetChange
+	26, // 21: gosdn.pnd.SetPathListRequest.change_request:type_name -> gosdn.pnd.ChangeRequest
+	1,  // 22: gosdn.pnd.ChangeRequest.api_op:type_name -> gosdn.pnd.ApiOperation
+	38, // 23: gosdn.pnd.SetOnd.sbi:type_name -> gosdn.southbound.SouthboundInterface
+	40, // 24: gosdn.pnd.SetOnd.transport_option:type_name -> gosdn.transport.TransportOption
+	2,  // 25: gosdn.pnd.SetSbi.sbi_type:type_name -> gosdn.pnd.SbiType
+	3,  // 26: gosdn.pnd.SetChange.op:type_name -> gosdn.pnd.Operation
+	4,  // 27: gosdn.pnd.SetResponse.status:type_name -> gosdn.pnd.Status
+	4,  // 28: gosdn.pnd.SetOndListResponse.status:type_name -> gosdn.pnd.Status
+	30, // 29: gosdn.pnd.SetOndListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	4,  // 30: gosdn.pnd.SetChangeListResponse.status:type_name -> gosdn.pnd.Status
+	30, // 31: gosdn.pnd.SetChangeListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	4,  // 32: gosdn.pnd.SetChangeResponse.status:type_name -> gosdn.pnd.Status
+	4,  // 33: gosdn.pnd.SetSbiListResponse.status:type_name -> gosdn.pnd.Status
+	30, // 34: gosdn.pnd.SetSbiListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	4,  // 35: gosdn.pnd.SetPathListResponse.status:type_name -> gosdn.pnd.Status
+	30, // 36: gosdn.pnd.SetPathListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	4,  // 37: gosdn.pnd.DeleteOndResponse.status:type_name -> gosdn.pnd.Status
+	5,  // 38: gosdn.pnd.PndService.GetOndList:input_type -> gosdn.pnd.GetOndListRequest
+	6,  // 39: gosdn.pnd.PndService.GetOnd:input_type -> gosdn.pnd.GetOndRequest
+	22, // 40: gosdn.pnd.PndService.SetOndList:input_type -> gosdn.pnd.SetOndListRequest
+	7,  // 41: gosdn.pnd.PndService.GetSbiList:input_type -> gosdn.pnd.GetSbiListRequest
+	8,  // 42: gosdn.pnd.PndService.GetSbi:input_type -> gosdn.pnd.GetSbiRequest
+	23, // 43: gosdn.pnd.PndService.SetSbiList:input_type -> gosdn.pnd.SetSbiListRequest
+	9,  // 44: gosdn.pnd.PndService.GetChangeList:input_type -> gosdn.pnd.GetChangeListRequest
+	10, // 45: gosdn.pnd.PndService.GetChange:input_type -> gosdn.pnd.GetChangeRequest
+	24, // 46: gosdn.pnd.PndService.SetChangeList:input_type -> gosdn.pnd.SetChangeListRequest
+	11, // 47: gosdn.pnd.PndService.GetPath:input_type -> gosdn.pnd.GetPathRequest
+	25, // 48: gosdn.pnd.PndService.SetPathList:input_type -> gosdn.pnd.SetPathListRequest
+	36, // 49: gosdn.pnd.PndService.DeleteOnd:input_type -> gosdn.pnd.DeleteOndRequest
+	13, // 50: gosdn.pnd.PndService.GetOndList:output_type -> gosdn.pnd.GetOndListResponse
+	12, // 51: gosdn.pnd.PndService.GetOnd:output_type -> gosdn.pnd.GetOndResponse
+	31, // 52: gosdn.pnd.PndService.SetOndList:output_type -> gosdn.pnd.SetOndListResponse
+	15, // 53: gosdn.pnd.PndService.GetSbiList:output_type -> gosdn.pnd.GetSbiListResponse
+	14, // 54: gosdn.pnd.PndService.GetSbi:output_type -> gosdn.pnd.GetSbiResponse
+	34, // 55: gosdn.pnd.PndService.SetSbiList:output_type -> gosdn.pnd.SetSbiListResponse
+	18, // 56: gosdn.pnd.PndService.GetChangeList:output_type -> gosdn.pnd.GetChangeListResponse
+	17, // 57: gosdn.pnd.PndService.GetChange:output_type -> gosdn.pnd.GetChangeResponse
+	32, // 58: gosdn.pnd.PndService.SetChangeList:output_type -> gosdn.pnd.SetChangeListResponse
+	16, // 59: gosdn.pnd.PndService.GetPath:output_type -> gosdn.pnd.GetPathResponse
+	35, // 60: gosdn.pnd.PndService.SetPathList:output_type -> gosdn.pnd.SetPathListResponse
+	37, // 61: gosdn.pnd.PndService.DeleteOnd:output_type -> gosdn.pnd.DeleteOndResponse
+	50, // [50:62] is the sub-list for method output_type
+	38, // [38:50] is the sub-list for method input_type
+	38, // [38:38] is the sub-list for extension type_name
+	38, // [38:38] is the sub-list for extension extendee
+	0,  // [0:38] is the sub-list for field type_name
 }
 
 func init() { file_gosdn_pnd_pnd_proto_init() }
diff --git a/api/go/gosdn/pnd/pnd.pb.gw.go b/api/go/gosdn/pnd/pnd.pb.gw.go
index 2b75200c8fad1fa6fe38831ee7293ad358a82c8b..2c59921a9a36b169854bf52d9cdbb2f9dc37c5c1 100644
--- a/api/go/gosdn/pnd/pnd.pb.gw.go
+++ b/api/go/gosdn/pnd/pnd.pb.gw.go
@@ -131,7 +131,7 @@ func request_PndService_GetOnd_0(ctx context.Context, marshaler runtime.Marshale
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "did")
 	}
 
-	protoReq.Did, err = runtime.StringSlice(val, ",")
+	protoReq.Did, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "did", err)
 	}
@@ -174,7 +174,7 @@ func local_request_PndService_GetOnd_0(ctx context.Context, marshaler runtime.Ma
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "did")
 	}
 
-	protoReq.Did, err = runtime.StringSlice(val, ",")
+	protoReq.Did, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "did", err)
 	}
@@ -359,7 +359,7 @@ func request_PndService_GetSbi_0(ctx context.Context, marshaler runtime.Marshale
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sid")
 	}
 
-	protoReq.Sid, err = runtime.StringSlice(val, ",")
+	protoReq.Sid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sid", err)
 	}
@@ -402,7 +402,7 @@ func local_request_PndService_GetSbi_0(ctx context.Context, marshaler runtime.Ma
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sid")
 	}
 
-	protoReq.Sid, err = runtime.StringSlice(val, ",")
+	protoReq.Sid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sid", err)
 	}
@@ -587,7 +587,7 @@ func request_PndService_GetChange_0(ctx context.Context, marshaler runtime.Marsh
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cuid")
 	}
 
-	protoReq.Cuid, err = runtime.String(val)
+	protoReq.Cuid, err = runtime.StringSlice(val, ",")
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cuid", err)
 	}
@@ -630,7 +630,7 @@ func local_request_PndService_GetChange_0(ctx context.Context, marshaler runtime
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cuid")
 	}
 
-	protoReq.Cuid, err = runtime.String(val)
+	protoReq.Cuid, err = runtime.StringSlice(val, ",")
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cuid", err)
 	}
diff --git a/api/openapiv2/gosdn_northbound.swagger.json b/api/openapiv2/gosdn_northbound.swagger.json
index 4a016bc2c27b39a0706fa3505d0640987c8a9acc..7752e8aa07811f91ea044176236fd0e4dcf505a3 100644
--- a/api/openapiv2/gosdn_northbound.swagger.json
+++ b/api/openapiv2/gosdn_northbound.swagger.json
@@ -146,12 +146,7 @@
             "name": "pid",
             "in": "path",
             "required": true,
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "collectionFormat": "csv",
-            "minItems": 1
+            "type": "string"
           },
           {
             "name": "timestamp",
@@ -383,7 +378,12 @@
             "name": "cuid",
             "in": "path",
             "required": true,
-            "type": "string"
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "collectionFormat": "csv",
+            "minItems": 1
           },
           {
             "name": "timestamp",
@@ -427,12 +427,7 @@
             "name": "did",
             "in": "path",
             "required": true,
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "collectionFormat": "csv",
-            "minItems": 1
+            "type": "string"
           },
           {
             "name": "timestamp",
@@ -795,12 +790,7 @@
             "name": "sid",
             "in": "path",
             "required": true,
-            "type": "array",
-            "items": {
-              "type": "string"
-            },
-            "collectionFormat": "csv",
-            "minItems": 1
+            "type": "string"
           },
           {
             "name": "timestamp",
@@ -1314,10 +1304,7 @@
           "format": "int64"
         },
         "pnd": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/pndPrincipalNetworkDomain"
-          }
+          "$ref": "#/definitions/pndPrincipalNetworkDomain"
         }
       }
     },
@@ -2479,6 +2466,9 @@
           "type": "string",
           "format": "int64"
         },
+        "id": {
+          "type": "string"
+        },
         "status": {
           "$ref": "#/definitions/gosdnpndStatus"
         }
@@ -2564,6 +2554,9 @@
         },
         "state": {
           "$ref": "#/definitions/pndChangeState"
+        },
+        "diff": {
+          "$ref": "#/definitions/gnmiNotification"
         }
       }
     },
@@ -2677,10 +2670,7 @@
           "description": "TODO: Check if this is really needed. Perhaps a reference to the PND's ID\nis also sufficient."
         },
         "ond": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/pndOrchestratedNetworkingDevice"
-          }
+          "$ref": "#/definitions/pndOrchestratedNetworkingDevice"
         }
       }
     },
@@ -2734,10 +2724,7 @@
           "description": "TODO: Check if this is really needed. Perhaps a reference to the PND's ID\nis also sufficient."
         },
         "sbi": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/southboundSouthboundInterface"
-          }
+          "$ref": "#/definitions/southboundSouthboundInterface"
         }
       }
     },
diff --git a/api/proto/buf.lock b/api/proto/buf.lock
index 60d8de11dc18ebb85fc6bab0acf9be9c0d7d0b24..87b5db40a38f740a05fd512626def460cf8ce415 100644
--- a/api/proto/buf.lock
+++ b/api/proto/buf.lock
@@ -4,7 +4,7 @@ deps:
   - remote: buf.build
     owner: googleapis
     repository: googleapis
-    commit: f3590c56d388417ebbedefae77ac12bf
+    commit: 8ab0a452adb64b36ac7a40ae95bd59b2
   - remote: buf.build
     owner: grpc-ecosystem
     repository: grpc-gateway
diff --git a/api/proto/gosdn/core/core.proto b/api/proto/gosdn/core/core.proto
index a55a8dd17293a84a0353569cb49aa55762ef46bc..d2476f3897755c07298973f159a11ca888ae96e6 100644
--- a/api/proto/gosdn/core/core.proto
+++ b/api/proto/gosdn/core/core.proto
@@ -35,25 +35,26 @@ service CoreService {
   }
 }
 
-message GetPndListRequest {
-  int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-}
 
 message GetPndRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  repeated string pid = 3;
+  string pid = 2;
 }
 
-message GetPndListResponse {
+message GetPndResponse {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  repeated .gosdn.pnd.PrincipalNetworkDomain pnd = 2;
+  .gosdn.pnd.PrincipalNetworkDomain pnd = 2;
 }
 
-message GetPndResponse {
-  int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  repeated .gosdn.pnd.PrincipalNetworkDomain pnd = 2;
+message GetPndListRequest {
+    int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
 }
 
+message GetPndListResponse {
+    int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
+    repeated .gosdn.pnd.PrincipalNetworkDomain pnd = 2;
+ }
+
 message CreatePndListRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
   repeated PndCreateProperties pnd = 2;
diff --git a/api/proto/gosdn/pnd/pnd.proto b/api/proto/gosdn/pnd/pnd.proto
index 11bed8ef564785395463955b363ba372fcff4da8..d68ef4940e68f6987808b4482fe8137136a9393f 100644
--- a/api/proto/gosdn/pnd/pnd.proto
+++ b/api/proto/gosdn/pnd/pnd.proto
@@ -118,34 +118,35 @@ service PndService {
 
 message GetOndListRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  string pid = 4;
+  string pid = 2;
 }
 
 message GetOndRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  repeated string did = 3;
-  string pid = 4;
+  string did = 2;
+  string pid = 3;
 }
 
 message GetSbiListRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  string pid = 4;
+  string pid = 2;
 }
+
 message GetSbiRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  repeated string sid = 3;
-  string pid = 4;
+  string sid = 2;
+  string pid = 3;
 }
 
 message GetChangeListRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  string pid = 4;
+  string pid = 2;
 }
 
 message GetChangeRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  string cuid = 3;
-  string pid = 4;
+  repeated string cuid = 2;
+  string pid = 3;
 }
 
 message GetPathRequest {
@@ -160,7 +161,7 @@ message GetOndResponse {
   // TODO: Check if this is really needed. Perhaps a reference to the PND's ID
   // is also sufficient.
   PrincipalNetworkDomain pnd = 2;
-  repeated OrchestratedNetworkingDevice ond = 3;
+  OrchestratedNetworkingDevice ond = 3;
 }
 
 message GetOndListResponse {
@@ -176,7 +177,7 @@ message GetSbiResponse {
   // TODO: Check if this is really needed. Perhaps a reference to the PND's ID
   // is also sufficient.
   PrincipalNetworkDomain pnd = 2;
-  repeated .gosdn.southbound.SouthboundInterface sbi = 3;
+  .gosdn.southbound.SouthboundInterface sbi = 3;
 }
 
 message GetSbiListResponse {
@@ -235,8 +236,8 @@ enum ChangeState {
 message Change {
   string id = 1;
   int64 age = 2;
-
   ChangeState state = 3;
+  gnmi.Notification diff = 4;
 }
 
 message SetOndListRequest {
@@ -310,7 +311,8 @@ message SetChange {
 
 message SetResponse{
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  Status status = 2;
+  string id = 2;
+  Status status = 3;
 }
 
 message SetOndListResponse{
@@ -344,8 +346,8 @@ message SetPathListResponse{
 
 message DeleteOndRequest {
   int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
-  string pid = 4;
-  string did = 5;
+  string pid = 2;
+  string did = 3;
 }
 
 message DeleteOndResponse {
diff --git a/cli/adapter/OndAdapter.go b/cli/adapter/OndAdapter.go
deleted file mode 100644
index b8e8da3083fa3680ab0724d21c4b05795f409d26..0000000000000000000000000000000000000000
--- a/cli/adapter/OndAdapter.go
+++ /dev/null
@@ -1 +0,0 @@
-package adapter
diff --git a/cli/adapter/PndAdapter.go b/cli/adapter/PndAdapter.go
index a03b5480bb0bb6bda6defd5aabacd862fb9a46d2..a02ac56ea36adfc4f457dd03484b76fbf1d8e8fa 100644
--- a/cli/adapter/PndAdapter.go
+++ b/cli/adapter/PndAdapter.go
@@ -5,15 +5,12 @@ import (
 
 	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/core"
 	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
-	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
-	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/change"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
 	"github.com/google/uuid"
 	"github.com/openconfig/goyang/pkg/yang"
-	log "github.com/sirupsen/logrus"
 	"golang.org/x/sync/errgroup"
 	"google.golang.org/protobuf/proto"
 )
@@ -69,22 +66,22 @@ func (p *PndAdapter) GetSbiSchemaTree(ctx context.Context, sid uuid.UUID) (map[s
 
 // GetDevice requests one or multiple devices belonging to a given
 // PrincipalNetworkDomain from the controller.
-func (p *PndAdapter) GetDevice(ctx context.Context, identifier ...string) ([]*ppb.OrchestratedNetworkingDevice, error) {
-	resp, err := api.GetDevice(ctx, p.endpoint, p.id.String(), identifier...)
+func (p *PndAdapter) GetDevice(ctx context.Context, identifier string) (*ppb.GetOndResponse, error) {
+	resp, err := api.GetDevice(ctx, p.endpoint, p.id.String(), identifier)
 	if err != nil {
 		return nil, err
 	}
-	return resp.Ond, nil
+	return resp, nil
 }
 
 // GetDevices requests all devices belonging to the PrincipalNetworkDomain
 // attached to this adapter.
-func (p *PndAdapter) GetDevices(ctx context.Context) ([]*ppb.OrchestratedNetworkingDevice, error) {
+func (p *PndAdapter) GetDevices(ctx context.Context) (*ppb.GetOndListResponse, error) {
 	resp, err := api.GetDevices(ctx, p.endpoint, p.id.String())
 	if err != nil {
 		return nil, err
 	}
-	return resp.Ond, nil
+	return resp, nil
 }
 
 // RemoveDevice removes a device from the controller
@@ -108,22 +105,21 @@ func (p *PndAdapter) RemovePnd(ctx context.Context, pid uuid.UUID) (*core.Delete
 // ChangeOND sends an API call to the controller requesting the creation of
 // a change from the provided Operation, path and value. The Change is marked
 // as Pending and times out after the specified timeout period
-func (p *PndAdapter) ChangeOND(ctx context.Context, duid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) (uuid.UUID, error) {
+func (p *PndAdapter) ChangeOND(ctx context.Context, duid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) (*ppb.SetPathListResponse, error) {
 	var v string
 	if len(value) != 0 {
 		v = value[0]
 	}
 	resp, err := api.ChangeRequest(ctx, p.endpoint, duid.String(), p.id.String(), path, v, operation)
 	if err != nil {
-		return uuid.Nil, err
+		return nil, err
 	}
-	log.Info(resp)
-	return uuid.Nil, err
+	return resp, err
 }
 
 // Request sends an API call to the controller requesting the specified path
 // for the specified device
-func (p *PndAdapter) Request(ctx context.Context, did uuid.UUID, path string) (proto.Message, error) {
+func (p *PndAdapter) Request(ctx context.Context, did uuid.UUID, path string) (*ppb.GetPathResponse, error) {
 	resp, err := api.GetPath(ctx, p.endpoint, p.id.String(), did.String(), path)
 	if err != nil {
 		return nil, err
@@ -169,22 +165,22 @@ func (p *PndAdapter) ContainsDevice(uuid.UUID) bool {
 
 // GetSbi sends an API call to the controller requesting the
 // registered SBI with the provided ID.
-func (p *PndAdapter) GetSbi(ctx context.Context, sid ...string) ([]*spb.SouthboundInterface, error) {
-	resp, err := api.GetSbi(ctx, p.endpoint, p.id.String(), sid...)
+func (p *PndAdapter) GetSbi(ctx context.Context, sid string) (*ppb.GetSbiResponse, error) {
+	resp, err := api.GetSbi(ctx, p.endpoint, p.id.String(), sid)
 	if err != nil {
 		return nil, err
 	}
-	return resp.Sbi, nil
+	return resp, nil
 }
 
 // GetSBIs sends an API call to the controller requesting the
 // registered SBIs. Not implemented, always returns nil
-func (p *PndAdapter) GetSBIs(ctx context.Context) ([]*spb.SouthboundInterface, error) {
+func (p *PndAdapter) GetSBIs(ctx context.Context) (*ppb.GetSbiListResponse, error) {
 	resp, err := api.GetSBIs(ctx, p.endpoint, p.id.String())
 	if err != nil {
 		return nil, err
 	}
-	return resp.Sbi, nil
+	return resp, nil
 }
 
 // ID returns the PND Adapter's UUID
@@ -199,57 +195,67 @@ func (p *PndAdapter) Endpoint() string {
 
 // PendingChanges sends an API call to the controller requesting
 // the UUIDs of all pending changes
-func (p *PndAdapter) PendingChanges(ctx context.Context) []uuid.UUID {
+func (p *PndAdapter) PendingChanges(ctx context.Context) ([]*ppb.Change, error) {
 	resp, err := api.GetChanges(ctx, p.endpoint, p.id.String())
 	if err != nil {
-		log.Error(err)
-		return nil
+		return nil, err
 	}
-	return filterChanges(ppb.ChangeState_CHANGE_STATE_PENDING, resp)
+	return filterChanges(ppb.ChangeState_CHANGE_STATE_PENDING, resp), nil
 }
 
 // CommittedChanges sends an API call to the controller requesting
 // the UUIDs of all committed changes
-func (p *PndAdapter) CommittedChanges(ctx context.Context) []uuid.UUID {
+func (p *PndAdapter) CommittedChanges(ctx context.Context) ([]*ppb.Change, error) {
 	resp, err := api.GetChanges(ctx, p.endpoint, p.id.String())
 	if err != nil {
-		log.Error(err)
-		return nil
+		return nil, err
 	}
-	return filterChanges(ppb.ChangeState_CHANGE_STATE_COMMITTED, resp)
+	return filterChanges(ppb.ChangeState_CHANGE_STATE_COMMITTED, resp), nil
 }
 
-// GetChange sends an API call to the controller requesting the specified change
-func (p *PndAdapter) GetChange(uuid.UUID) (change.Change, error) {
-	return nil, &errors.ErrNotYetImplemented{}
+// ConfirmedChanges sends an API call to the controller requesting
+// the UUIDs of all confirmed changes
+func (p *PndAdapter) ConfirmedChanges(ctx context.Context) ([]*ppb.Change, error) {
+	resp, err := api.GetChanges(ctx, p.endpoint, p.id.String())
+	if err != nil {
+		return nil, err
+	}
+	return filterChanges(ppb.ChangeState_CHANGE_STATE_CONFIRMED, resp), nil
+}
+
+// GetChange sends an API call to the controller requesting one or more changes
+// for the specific PND
+func (p *PndAdapter) GetChange(ctx context.Context, identifier ...string) (*ppb.GetChangeResponse, error) {
+	resp, err := api.GetChange(ctx, p.endpoint, p.id.String(), identifier...)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
 }
 
 // Commit sends an API call to the controller committing the specified change
-func (p *PndAdapter) Commit(ctx context.Context, cuid uuid.UUID) error {
+func (p *PndAdapter) Commit(ctx context.Context, cuid uuid.UUID) (*ppb.SetChangeListResponse, error) {
 	resp, err := api.Commit(ctx, p.endpoint, p.id.String(), cuid.String())
 	if err != nil {
-		return err
+		return nil, err
 	}
-	log.Info(resp)
-	return nil
+	return resp, nil
 }
 
 // Confirm sends an API call to the controller confirming the specified change
-func (p *PndAdapter) Confirm(ctx context.Context, cuid uuid.UUID) error {
+func (p *PndAdapter) Confirm(ctx context.Context, cuid uuid.UUID) (*ppb.SetChangeListResponse, error) {
 	resp, err := api.Confirm(ctx, p.endpoint, p.id.String(), cuid.String())
 	if err != nil {
-		return err
+		return nil, err
 	}
-	log.Info(resp)
-	return nil
+	return resp, nil
 }
 
-func filterChanges(state ppb.ChangeState, resp *ppb.GetChangeListResponse) []uuid.UUID {
-	changes := make([]uuid.UUID, 0)
+func filterChanges(state ppb.ChangeState, resp *ppb.GetChangeListResponse) []*ppb.Change {
+	changes := make([]*ppb.Change, 0)
 	for _, ch := range resp.Change {
 		if ch.State == state {
-			id, _ := uuid.Parse(ch.Id)
-			changes = append(changes, id)
+			changes = append(changes, ch)
 		}
 	}
 	return changes
diff --git a/cli/adapter/PndAdapter_test.go b/cli/adapter/PndAdapter_test.go
index 2f5b1612abd5b6345387b47cfd8ecf4e2dd7c141..2c49e7804c452cab296fbd9ff5405042213deff0 100644
--- a/cli/adapter/PndAdapter_test.go
+++ b/cli/adapter/PndAdapter_test.go
@@ -385,7 +385,7 @@ func TestPndAdapter_PendingChanges(t *testing.T) {
 				id:       tt.fields.id,
 				endpoint: tt.fields.endpoint,
 			}
-			if got := p.PendingChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) {
+			if got, _ := p.PendingChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("PndAdapter.PendingChanges() = %v, want %v", got, tt.want)
 			}
 		})
@@ -410,7 +410,7 @@ func TestPndAdapter_CommittedChanges(t *testing.T) {
 				id:       tt.fields.id,
 				endpoint: tt.fields.endpoint,
 			}
-			if got := p.CommittedChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) {
+			if got, _ := p.CommittedChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("PndAdapter.CommittedChanges() = %v, want %v", got, tt.want)
 			}
 		})
@@ -423,7 +423,7 @@ func TestPndAdapter_GetChange(t *testing.T) {
 		endpoint string
 	}
 	type args struct {
-		in uuid.UUID
+		in []string
 	}
 	tests := []struct {
 		name    string
@@ -440,7 +440,7 @@ func TestPndAdapter_GetChange(t *testing.T) {
 				id:       tt.fields.id,
 				endpoint: tt.fields.endpoint,
 			}
-			got, err := p.GetChange(tt.args.in)
+			got, err := p.GetChange(context.TODO(), tt.args.in...)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("PndAdapter.GetChange() error = %v, wantErr %v", err, tt.wantErr)
 				return
@@ -474,7 +474,7 @@ func TestPndAdapter_Commit(t *testing.T) {
 				id:       tt.fields.id,
 				endpoint: tt.fields.endpoint,
 			}
-			if err := p.Commit(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr {
+			if _, err := p.Commit(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr {
 				t.Errorf("PndAdapter.Commit() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -503,7 +503,7 @@ func TestPndAdapter_Confirm(t *testing.T) {
 				id:       tt.fields.id,
 				endpoint: tt.fields.endpoint,
 			}
-			if err := p.Confirm(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr {
+			if _, err := p.Confirm(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr {
 				t.Errorf("PndAdapter.Confirm() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
diff --git a/cli/cmd/changeCommit.go b/cli/cmd/changeCommit.go
index 8bdc0ea4190d9acf8a47492bcb975566becda5f9..0994ee2f6e302db03c9ee5634a59e7782f255368 100644
--- a/cli/cmd/changeCommit.go
+++ b/cli/cmd/changeCommit.go
@@ -33,7 +33,7 @@ package cmd
 
 import (
 	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 )
 
@@ -48,10 +48,14 @@ Change UUID must be specified as positional argument.`,
 	Run: func(cmd *cobra.Command, args []string) {
 		cuid, err := uuid.Parse(args[0])
 		if err != nil {
-			log.Fatal(err)
+			pterm.Error.Println(err)
 		}
-		if err := pndAdapter.Commit(createContextWithAuthorization(), cuid); err != nil {
-			log.Fatal(err)
+		resp, err := pndAdapter.Commit(createContextWithAuthorization(), cuid)
+		if err != nil {
+			pterm.Error.Println(err)
+		}
+		for _, r := range resp.GetResponses() {
+			pterm.Info.Println(r.String())
 		}
 	},
 }
diff --git a/cli/cmd/changeConfirm.go b/cli/cmd/changeConfirm.go
index 4fa511580fcd55858702c74fb1bf2e0389498b07..20a49e536a6cb4509d28e1446d17f258b022bab8 100644
--- a/cli/cmd/changeConfirm.go
+++ b/cli/cmd/changeConfirm.go
@@ -33,7 +33,7 @@ package cmd
 
 import (
 	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 )
 
@@ -48,10 +48,15 @@ Change UUID must be specified as positional argument`,
 	Run: func(cmd *cobra.Command, args []string) {
 		cuid, err := uuid.Parse(args[0])
 		if err != nil {
-			log.Fatal(err)
+			pterm.Error.Println(err)
 		}
-		if err := pndAdapter.Confirm(createContextWithAuthorization(), cuid); err != nil {
-			log.Fatal(err)
+
+		resp, err := pndAdapter.Confirm(createContextWithAuthorization(), cuid)
+		if err != nil {
+			pterm.Error.Println(err)
+		}
+		for _, r := range resp.GetResponses() {
+			pterm.Info.Println(r.String())
 		}
 	},
 }
diff --git a/cli/cmd/init.go b/cli/cmd/changeGet.go
similarity index 57%
rename from cli/cmd/init.go
rename to cli/cmd/changeGet.go
index f2d809e8744a915d4c8c674c3a4abcc199fbf5c6..6495b1e3f85ba5e4c3dae7913878031f2b8ae373 100644
--- a/cli/cmd/init.go
+++ b/cli/cmd/changeGet.go
@@ -32,44 +32,41 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	"fmt"
-	"os"
-
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
+	"google.golang.org/protobuf/encoding/protojson"
 )
 
-var controllerAPIEndpoint string
+// confirmCmd represents the confirm command
+var getCmd = &cobra.Command{
+	Use:   "get [uuid]",
+	Args:  cobra.ExactArgs(1),
+	Short: "returns information about the requested change",
+	Long: `Returns detailed information about a specific change. The
+    changes UUID has to be specified via a positional argument.`,
 
-// initCmd represents the init command
-var initCmd = &cobra.Command{
-	Use:   "init",
-	Short: "initialise controller",
-	Long: `Initialise PND and SBI and saves values to config file on controller.
-The --controller flag is required to change the controller address`,
+	Run: func(cmd *cobra.Command, args []string) {
+		changes, err := pndAdapter.GetChange(createContextWithAuthorization(), args[0])
+		if err != nil {
+			pterm.Error.Println(err)
+		}
+		for _, c := range changes.GetChange() {
+			title := pterm.Sprintf("Change with ID: %s", c.GetId())
+			panel1 := pterm.DefaultBox.WithTitle("Age:").Sprint(c.GetAge())
+			panel2 := pterm.DefaultBox.WithTitle("State:").Sprint(c.GetState())
+			panel3 := pterm.DefaultBox.WithTitle("Diff:").Sprint(protojson.Format(c.GetDiff()))
 
-	RunE: func(cmd *cobra.Command, args []string) error {
-		log.Infof("New controller address: %v", viper.GetString("controllerAPIEndpoint"))
+			panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{
+				{{Data: panel1}},
+				{{Data: panel2}},
+				{{Data: panel3}},
+			}).Srender()
 
-		if err := viper.WriteConfig(); err != nil {
-			fmt.Fprintln(os.Stderr, "Could not write config:", err)
+			pterm.DefaultBox.WithTitle(title).WithTitleTopCenter().WithRightPadding(0).WithBottomPadding(0).Println(panels)
 		}
-		return nil
 	},
 }
 
 func init() {
-	rootCmd.AddCommand(initCmd)
-
-	initCmd.Flags().StringVar(&controllerAPIEndpoint, "controller", "gosdn-develop.apps.ocp.fbi.h-da.de:55055", "address of the controller")
-	err := viper.BindPFlag("controllerAPIEndpoint", initCmd.Flags().Lookup("controller"))
-	if err != nil {
-		fmt.Fprintln(os.Stderr, "Could not bind controllerAPIEndpoint:", err)
-	}
-
-	// Set controller flag as required (possibly not?)
-	//if err := initCmd.MarkFlagRequired("controller"); err != nil {
-	// 	fmt.Fprintln(os.Stderr, "Could not mark controller flag as required:", err)
-	//}
+	changeCmd.AddCommand(getCmd)
 }
diff --git a/cli/cmd/changeList.go b/cli/cmd/changeList.go
index dcd3dc4f4e37a3e480a1a8d7feeacdb673a17802..af52241337c28aacfcbb372493fb9fba9953beb2 100644
--- a/cli/cmd/changeList.go
+++ b/cli/cmd/changeList.go
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 )
 
@@ -43,17 +43,33 @@ var changeListCmd = &cobra.Command{
 	Short:   "list all changes",
 	Long:    `Lists all configuration changes with their UUIDs.`,
 
-	Run: func(cmd *cobra.Command, args []string) {
-		committed := pndAdapter.CommittedChanges(createContextWithAuthorization())
-		log.Info("committed changes:")
-		for i, ch := range committed {
-			log.Infof("    Change %v: %v", i+1, ch.String())
+	RunE: func(cmd *cobra.Command, args []string) error {
+		spinner, _ := pterm.DefaultSpinner.Start("Process change list request")
+		committed, err := pndAdapter.CommittedChanges(createContextWithAuthorization())
+		if err != nil {
+			spinner.Fail(err)
+			return err
 		}
-		pending := pndAdapter.PendingChanges(createContextWithAuthorization())
-		log.Info("pending changes:")
-		for i, ch := range pending {
-			log.Infof("    Change %v: %v", i+1, ch.String())
+		pending, err := pndAdapter.PendingChanges(createContextWithAuthorization())
+		if err != nil {
+			spinner.Fail(err)
+			return err
 		}
+
+		// TODO: maybe we want to return more information about changes? E.g.,
+		// the diff of the change (probably only for a single get of a change).
+		// This would require us to change pndAdapter methods.
+		data := pterm.TableData{[]string{"UUID", "Status"}}
+		for _, ch := range pending {
+			data = append(data, []string{ch.String(), "pending"})
+		}
+		for _, ch := range committed {
+			data = append(data, []string{ch.String(), "commited"})
+		}
+
+		spinner.Success()
+		pterm.DefaultTable.WithHasHeader().WithData(data).Render()
+		return nil
 	},
 }
 
diff --git a/cli/cmd/deviceCreate.go b/cli/cmd/deviceCreate.go
index 56781bf23682bf5c68c2078216d8f04c1d91d60d..efd182a0dfcb0516684fb79a0bd3d74e7aec7048 100644
--- a/cli/cmd/deviceCreate.go
+++ b/cli/cmd/deviceCreate.go
@@ -33,9 +33,8 @@ package cmd
 
 import (
 	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
-	"google.golang.org/protobuf/encoding/protojson"
 
 	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
@@ -50,8 +49,10 @@ Device address must be provided with IP and port,e.g., 192.168.1.1:6030. User cr
 if they diverge from the default credentials (user:'admin' and pw:'arista').`,
 
 	RunE: func(cmd *cobra.Command, args []string) error {
+		spinner, _ := pterm.DefaultSpinner.Start("Creating new device")
 		err := checkIPPort(address)
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
 
@@ -73,16 +74,19 @@ if they diverge from the default credentials (user:'admin' and pw:'arista').`,
 		}
 		sid, err := uuid.Parse(cliSbi)
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
 
 		resp, err := pndAdapter.AddDevice(createContextWithAuthorization(), deviceName, opt, sid)
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
 
-		log.Info(protojson.Format(resp))
-
+		for _, r := range resp.GetResponses() {
+			spinner.Success("Device has been created with ID: ", r.GetId())
+		}
 		return nil
 	},
 }
diff --git a/cli/cmd/deviceDelete.go b/cli/cmd/deviceDelete.go
index 82769ea903f055eed956ee4ab75f73f58b249e3b..c354ccc2c5a335df172704914c7d8e976539eaf9 100644
--- a/cli/cmd/deviceDelete.go
+++ b/cli/cmd/deviceDelete.go
@@ -34,7 +34,7 @@ package cmd
 import (
 	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 )
 
@@ -46,17 +46,27 @@ var deviceDeleteCmd = &cobra.Command{
 	Long: `Delete a path for a given orchestrated network device.
 The device UUID and request path must be specified as a positional arguments.`,
 
-	Run: func(cmd *cobra.Command, args []string) {
+	RunE: func(cmd *cobra.Command, args []string) error {
+		spinner, _ := pterm.DefaultSpinner.Start("Create a path deletion request.")
 		did, err := uuid.Parse(args[0])
 		if err != nil {
-			log.Fatal(err)
+			spinner.Fail(err)
+			return err
 		}
-		log.Info(pndAdapter.ChangeOND(
+		resp, err := pndAdapter.ChangeOND(
 			createContextWithAuthorization(),
 			did,
 			ppb.ApiOperation_API_OPERATION_DELETE,
 			args[1],
-		))
+		)
+		for _, r := range resp.Responses {
+			if r.Status == ppb.Status_STATUS_OK {
+				spinner.Success("A change for path deletion for Device: ", did.String(), "has been created -> Change ID: ", r.GetId())
+			} else {
+				spinner.Fail("An error occured while creating a path deletion request for Device with ID: ", r.GetId(), r.GetStatus())
+			}
+		}
+		return nil
 	},
 }
 
diff --git a/cli/cmd/deviceGet.go b/cli/cmd/deviceGet.go
index 0bbaaff0b4f9a0435fd4329028ff3bed9cd34bca..271eeca4a3043c63afa7a0f4b02a70f39ab6f364 100644
--- a/cli/cmd/deviceGet.go
+++ b/cli/cmd/deviceGet.go
@@ -33,7 +33,7 @@ package cmd
 
 import (
 	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 	"google.golang.org/protobuf/encoding/protojson"
 )
@@ -46,22 +46,37 @@ var deviceGetCmd = &cobra.Command{
 	Long: `Requests a path from a specified orchestrated network device on the controller.
 The device UUID and request path must be specified as a positional arguments.`,
 
-	Run: func(cmd *cobra.Command, args []string) {
+	RunE: func(cmd *cobra.Command, args []string) error {
 		did, err := uuid.Parse(args[0])
 		if err != nil {
-			log.Fatal(err)
+			pterm.Error.Println(err)
+			return err
 		}
 
-		message, err := pndAdapter.Request(
+		res, err := pndAdapter.Request(
 			createContextWithAuthorization(),
 			did,
 			args[1],
 		)
 		if err != nil {
-			log.Error(err)
+			pterm.Error.Println(err)
+			return err
 		}
 
-		log.Info(protojson.Format(message))
+		for _, n := range res.Device {
+			panel1 := pterm.DefaultBox.WithTitle("Timestamp:").Sprint(n.GetTimestamp())
+			panel2 := pterm.DefaultBox.WithTitle("Requested Path:").Sprint(args[1])
+			panel3 := pterm.DefaultBox.WithTitle("Update:").Sprint(protojson.Format(n.Update[0]))
+
+			panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{
+				{{Data: panel1}},
+				{{Data: panel2}},
+				{{Data: panel3}},
+			}).Srender()
+
+			pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels)
+		}
+		return nil
 	},
 }
 
diff --git a/cli/cmd/deviceList.go b/cli/cmd/deviceList.go
index 3e0d7408fd8067b9351eb4166eb6e6d3485ca25c..c74939942fd69fa3411cde5301189b4d9d1afde7 100644
--- a/cli/cmd/deviceList.go
+++ b/cli/cmd/deviceList.go
@@ -32,8 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 
 	"github.com/spf13/cobra"
 )
@@ -46,23 +45,22 @@ var deviceListCmd = &cobra.Command{
 	Long:    "List all orchestrated network devices within the current PND.",
 
 	RunE: func(cmd *cobra.Command, args []string) error {
-		respONDs, err := pndAdapter.GetDevices(createContextWithAuthorization())
+		spinner, _ := pterm.DefaultSpinner.Start("Fetching data from controller")
+
+		resp, err := pndAdapter.GetDevices(createContextWithAuthorization())
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
 
-		for i, dev := range respONDs {
-			log.Infof("OND %v: name: %v, uuid: %v", i+1, dev.Name, dev.Id)
-			sid, err := uuid.Parse(dev.GetSbi().GetId())
-			if err != nil {
-				return err
-			}
-			tree, err := pndAdapter.GetSbiSchemaTree(createContextWithAuthorization(), sid)
-			if err != nil {
-				return err
-			}
-			log.Infof("   SchemaTree: %v", tree)
+		data := pterm.TableData{[]string{"UUID", "Name", "SBI-UUID", "SBI-Type"}}
+		for _, dev := range resp.GetOnd() {
+			data = append(data, []string{dev.GetId(), dev.GetName(), dev.GetSbi().GetId(), dev.GetSbi().GetType().String()})
 		}
+
+		spinner.Success()
+
+		pterm.DefaultTable.WithHasHeader().WithData(data).Render()
 		return nil
 	},
 }
diff --git a/cli/cmd/deviceRemove.go b/cli/cmd/deviceRemove.go
index 37170c2de6127f7fe7cbc97705a87525dec29dfb..6cbdf8125fb4750ce1d2c3b6f893ed539e86604c 100644
--- a/cli/cmd/deviceRemove.go
+++ b/cli/cmd/deviceRemove.go
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 
 	"github.com/google/uuid"
 	"github.com/spf13/cobra"
@@ -48,15 +48,18 @@ var deviceRemoveCmd = &cobra.Command{
 The device UUID must be specified as a positional argument.`,
 
 	RunE: func(cmd *cobra.Command, args []string) error {
+		spinner, _ := pterm.DefaultSpinner.Start("Removing device with ID: ", args[0])
 		did, err := uuid.Parse(args[0])
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		resp, err := pndAdapter.RemoveDevice(createContextWithAuthorization(), did)
+		_, err = pndAdapter.RemoveDevice(createContextWithAuthorization(), did)
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		log.Infof("Deletion of OND with ID %v: %s", did, resp.GetStatus().String())
+		spinner.Success("PND has been deleted, ID: ", did.String())
 		return nil
 	},
 }
diff --git a/cli/cmd/deviceSet.go b/cli/cmd/deviceSet.go
index a8088d34a9e67c18a23d96e971b26198eaa64d55..8cd63cb2ad629f880b981f0f451ac86f0a16eb63 100644
--- a/cli/cmd/deviceSet.go
+++ b/cli/cmd/deviceSet.go
@@ -34,7 +34,7 @@ package cmd
 import (
 	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	"github.com/google/uuid"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 )
 
@@ -52,25 +52,38 @@ The device UUID, request path and value must be specified as positional argument
 To enable replacing behaviour (destructive!), set the --replace flag."`,
 
 	Run: func(cmd *cobra.Command, args []string) {
+		spinner, _ := pterm.DefaultSpinner.Start("Create a path set request.")
 		did, err := uuid.Parse(args[0])
 		if err != nil {
-			log.Fatal(err)
+			spinner.Fail(err)
 		}
 		var operation ppb.ApiOperation
 		if replace {
 			operation = ppb.ApiOperation_API_OPERATION_REPLACE
-			log.Info("Replace")
+			spinner.UpdateText("Replace generated and sent")
 		} else {
 			operation = ppb.ApiOperation_API_OPERATION_UPDATE
-			log.Info("Update")
+			spinner.UpdateText("Update generated and sent")
 		}
-		log.Info(pndAdapter.ChangeOND(
+
+		resp, err := pndAdapter.ChangeOND(
 			createContextWithAuthorization(),
 			did,
 			operation,
 			args[1],
 			args[2],
-		))
+		)
+		if err != nil {
+			spinner.Fail(err)
+		}
+
+		for _, r := range resp.GetResponses() {
+			if r.Status == ppb.Status_STATUS_OK {
+				spinner.Success("A change for Device: ", did.String(), "has been created -> Change ID: ", r.GetId())
+			} else {
+				spinner.Fail("An error occured while creating a path set request for Device with ID: ", r.GetId(), r.GetStatus())
+			}
+		}
 	},
 }
 
diff --git a/cli/cmd/deviceShow.go b/cli/cmd/deviceShow.go
index 7fb4198839ae0d72ce2995221af22efa315e5ef6..12b08b7269fbb435d4e83556122789a16d4a222a 100644
--- a/cli/cmd/deviceShow.go
+++ b/cli/cmd/deviceShow.go
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 )
 
@@ -46,8 +46,30 @@ Device UUID or name must be specified as a positional argument.
 The device information returned is the information as currently stored in the controller.
 The actual device is not queried directly.`,
 
-	Run: func(cmd *cobra.Command, args []string) {
-		log.Info(pndAdapter.GetDevice(createContextWithAuthorization(), args[0]))
+	RunE: func(cmd *cobra.Command, args []string) error {
+		resp, err := pndAdapter.GetDevice(createContextWithAuthorization(), args[0])
+		if err != nil {
+			pterm.Error.Println(err)
+			return err
+		}
+
+		dev := resp.GetOnd()
+
+		panel1 := pterm.DefaultBox.WithTitle("UUID:").Sprint(dev.Id)
+		panel2 := pterm.DefaultBox.WithTitle("Name:").Sprint(dev.Name)
+		panel3 := pterm.DefaultBox.WithTitle("SBI-UUID:").Sprint(dev.Sbi.Id)
+		panel4 := pterm.DefaultBox.WithTitle("SBI-Type:").Sprint(dev.Sbi.Type.String())
+
+		panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{
+			{{Data: panel1}},
+			{{Data: panel2}},
+			{{Data: panel3}},
+			{{Data: panel4}},
+		}).Srender()
+
+		pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels)
+
+		return nil
 	},
 }
 
diff --git a/cli/cmd/login.go b/cli/cmd/login.go
index 3d9aba572e887642340628b92979cffec0662dcf..e1c8fdeb49fea104d263dbcc81dfe07f81eb63a7 100644
--- a/cli/cmd/login.go
+++ b/cli/cmd/login.go
@@ -35,7 +35,7 @@ import (
 	"context"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
@@ -48,25 +48,26 @@ var loginCmd = &cobra.Command{
     User credentials need to be provided in the body`,
 
 	RunE: func(cmd *cobra.Command, args []string) error {
+		spinner, _ := pterm.DefaultSpinner.Start("Login attempt for user: ", nbUserName)
+
+		if controllerAPIEndpoint != "" {
+			if err := viper.WriteConfig(); err != nil {
+				pterm.Error.Println("Could not write config:", err)
+			}
+			pterm.Info.Println("New controller address: ", viper.GetString("controllerAPIEndpoint"))
+		}
+
 		// TODO: maybe add credentials in context instead of context.TODO()
 		resp, err := api.Login(context.TODO(), viper.GetString("controllerAPIEndpoint"), nbUserName, nbUserPwd)
 		if err != nil {
+			spinner.Fail("Login failed: ", err)
 			return err
 		}
 
-		userToken = resp.Token
-
-		if err := api.Init(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint")); err != nil {
-			return err
-		}
+		spinner.Success("Authentication for ", nbUserName, " was successful.")
 
-		sbiResp, err := api.GetSBIs(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), viper.GetString("CLI_PND"))
-		if err != nil {
-			return err
-		}
-		sid := sbiResp.Sbi[0].GetId()
-		viper.Set("CLI_SBI", sid)
-		log.Infof("SBI: %v", sid)
+		userToken = resp.Token
+		pterm.Info.Println("Authentication-User-Token:", userToken)
 
 		return nil
 	},
@@ -74,10 +75,17 @@ var loginCmd = &cobra.Command{
 
 var nbUserName string
 var nbUserPwd string
+var controllerAPIEndpoint string
 
 func init() {
 	rootCmd.AddCommand(loginCmd)
 
 	loginCmd.Flags().StringVar(&nbUserName, "u", "", "username for login")
 	loginCmd.Flags().StringVar(&nbUserPwd, "p", "", "pwd for login")
+	loginCmd.Flags().StringVar(&controllerAPIEndpoint, "controller", viper.GetString("controllerAPIEndpoint"), "address of the controller")
+
+	err := viper.BindPFlag("controllerAPIEndpoint", loginCmd.Flags().Lookup("controller"))
+	if err != nil {
+		pterm.Error.Println("Could not bind controllerAPIEndpoint:", err)
+	}
 }
diff --git a/cli/cmd/pndCreate.go b/cli/cmd/pndCreate.go
index f08d429d2685139006200e9ed21949baf79d9d7f..a2859604d68fe38b34a252aa1d56b5b9354346a2 100644
--- a/cli/cmd/pndCreate.go
+++ b/cli/cmd/pndCreate.go
@@ -32,18 +32,17 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
+	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/core"
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
-	"google.golang.org/protobuf/encoding/protojson"
-
-	log "github.com/sirupsen/logrus"
 )
 
 // pndCreateCmd represents the create command
 var pndCreateCmd = &cobra.Command{
 	Use:   "create [description]",
-	Args:  cobra.ExactArgs(1),
+	Args:  cobra.ExactArgs(0),
 	Short: "creates a new principal network domain to the controller",
 	Long: `A principal network domain is a main networking entity. This can be a
 campus building or site.
@@ -52,21 +51,31 @@ A description must be passed as positional argument. A name and default SBI can
 passed using parameters.`,
 
 	RunE: func(cmd *cobra.Command, args []string) error {
-		resp, err := api.AddPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), pndName, args[0], pndDefaultSbi)
+		spinner, _ := pterm.DefaultSpinner.Start("Creating new PND")
+		resp, err := api.AddPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), pndName, pndDescription, pndDefaultSbi)
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		log.Info(protojson.Format(resp))
+
+		if resp.Status == core.Status_STATUS_OK {
+			spinner.Success("PND has been created with name: ", pndName)
+		} else {
+			spinner.Fail("Failed creating the PND with name: ", pndName)
+		}
+
 		return nil
 	},
 }
 
 var pndName string
 var pndDefaultSbi string
+var pndDescription string
 
 func init() {
 	pndCmd.AddCommand(pndCreateCmd)
 
 	pndCreateCmd.Flags().StringVar(&pndName, "name", "", "the name of the pnd")
+	pndCreateCmd.Flags().StringVar(&pndDescription, "description", "", "description of the pnd")
 	pndCreateCmd.Flags().StringVar(&pndDefaultSbi, "sbi", "openconfig", "the default SBI of the pnd")
 }
diff --git a/cli/cmd/pndGet.go b/cli/cmd/pndGet.go
index ef5e36a32d68e9f149ca293ab10a6b51dfce03d8..735018a6f0077c51b07a5ba0c305d08d9b1c2954 100644
--- a/cli/cmd/pndGet.go
+++ b/cli/cmd/pndGet.go
@@ -32,7 +32,7 @@ package cmd
 
 import (
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
@@ -40,17 +40,31 @@ import (
 // pndGetCmd represents the get command
 var pndGetCmd = &cobra.Command{
 	Use:   "get",
-	Short: "get one or multiple PNDs by uuid or name and print them to stdout",
-	Long:  `Get one or multiple PNDs by uuid or name and print them to stdout.`,
+	Args:  cobra.ExactArgs(1),
+	Short: "Request a PND by uuid.",
+	Long:  `Request a PND specified by uuid. The PND's UUID, Name and Description are returned.`,
 
 	RunE: func(cmd *cobra.Command, args []string) error {
-		resp, err := api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), args...)
+		spinner, _ := pterm.DefaultSpinner.Start("Fetching requested PNDs from controller.")
+		resp, err := api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), args[0])
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		for i, pnd := range resp.Pnd {
-			log.Infof("PND %v: %v\n\tuuid: %v", i+1, pnd.Name, pnd.Id)
-		}
+
+		pnd := resp.Pnd
+		panel1 := pterm.DefaultBox.WithTitle("UUID:").Sprint(pnd.Id)
+		panel2 := pterm.DefaultBox.WithTitle("Name:").Sprint(pnd.Name)
+		panel3 := pterm.DefaultBox.WithTitle("Description:").Sprint(pnd.Description)
+
+		panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{
+			{{Data: panel1}},
+			{{Data: panel2}},
+			{{Data: panel3}},
+		}).Srender()
+
+		spinner.Success()
+		pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels)
 		return nil
 	},
 }
diff --git a/cli/cmd/pndList.go b/cli/cmd/pndList.go
index 2f44d74b661e3df3ab5593eb7d2d93d05dcb6868..65006b0c7705f8896abd7c81900420a23be2bee4 100644
--- a/cli/cmd/pndList.go
+++ b/cli/cmd/pndList.go
@@ -33,7 +33,7 @@ package cmd
 
 import (
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 
 	"github.com/spf13/cobra"
 )
@@ -46,14 +46,21 @@ var pndListCmd = &cobra.Command{
 	Long:    `List all information about the current PND.`,
 
 	RunE: func(cmd *cobra.Command, args []string) error {
-
-		resp, err := api.GetPnd(createContextWithAuthorization(), pndAdapter.Endpoint(), pndAdapter.ID().String())
+		spinner, _ := pterm.DefaultSpinner.Start("Fetching PND list from controller")
+		resp, err := api.GetPnds(createContextWithAuthorization(), pndAdapter.Endpoint())
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		for i, pnd := range resp.Pnd {
-			log.Infof("PND %v: name: %v, uuid: %v", i+1, pnd.Name, pnd.Id)
+
+		data := pterm.TableData{[]string{"UUID", "Name", "Description"}}
+		for _, pnd := range resp.Pnd {
+			data = append(data, []string{pnd.GetId(), pnd.GetName(), pnd.GetDescription()})
 		}
+
+		spinner.Success()
+
+		pterm.DefaultTable.WithHasHeader().WithData(data).Render()
 		return nil
 	},
 }
diff --git a/cli/cmd/pndRemove.go b/cli/cmd/pndRemove.go
index ed4890a7581d014c938eef65a7c5db2f4cd3b03d..98fb573ee900a245d8e39e6312876a9e01d25d06 100644
--- a/cli/cmd/pndRemove.go
+++ b/cli/cmd/pndRemove.go
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 
 	"github.com/google/uuid"
 	"github.com/spf13/cobra"
@@ -42,19 +42,22 @@ import (
 var pndRemoveCmd = &cobra.Command{
 	Use:     "remove",
 	Aliases: []string{"rm"},
-	Short:   "TODO - not yet implemented",
-	Long:    `TODO - not yet implemented`,
+	Short:   "Removes the PND with the provided ID",
+	Long:    "Removes the PND with the provided ID",
 
 	RunE: func(cmd *cobra.Command, args []string) error {
+		spinner, _ := pterm.DefaultSpinner.Start("Removing PND with ID: ", args[0])
 		pid, err := uuid.Parse(args[0])
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		resp, err := pndAdapter.RemovePnd(createContextWithAuthorization(), pid)
+		_, err = pndAdapter.RemovePnd(createContextWithAuthorization(), pid)
 		if err != nil {
+			spinner.Fail(err)
 			return err
 		}
-		log.Infof("Deletion of PND with ID %v: %s", pid, resp.GetStatus().String())
+		spinner.Success("PND has been deleted, ID: ", pid.String())
 		return nil
 	},
 }
diff --git a/cli/cmd/pndUse.go b/cli/cmd/pndUse.go
index 22be64cab7dfa2a0402b4c1b828a36c1f307e4ac..f3f77d7970d321bda990c5f658e19093ad4fc6ba 100644
--- a/cli/cmd/pndUse.go
+++ b/cli/cmd/pndUse.go
@@ -34,7 +34,7 @@ package cmd
 import (
 	"code.fbi.h-da.de/danet/gosdn/cli/adapter"
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
-	log "github.com/sirupsen/logrus"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
@@ -51,25 +51,32 @@ var pndUseCmd = &cobra.Command{
 
 		newPndAdapter, err := adapter.NewPndAdapter(newPND, viper.GetString("controllerAPIEndpoint"))
 		if err != nil {
-			log.Fatal(err)
+			pterm.Error.Println(err)
 			return err
 		}
 
 		_, err = api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), newPND)
 		if err != nil {
-			log.Fatal(err)
+			pterm.Error.Println(err)
+			return err
+		}
+
+		sbi, err := api.GetSBIs(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), newPND)
+		if err != nil {
+			pterm.Error.Println(err)
 			return err
 		}
 
 		viper.Set("CLI_PND", newPND)
+		viper.Set("CLI_SBI", sbi.GetSbi()[0].GetId())
 
 		err = viper.WriteConfig()
 		if err != nil {
-			log.Fatal(err)
+			pterm.Error.Println(err)
 			return err
 		}
 		pndAdapter = newPndAdapter
-		log.Infof("PND with ID: %s set for usage", pndAdapter.ID().String())
+		pterm.Info.Printf("PND with ID: %s has been set for usage.\n", pndAdapter.ID().String())
 		return nil
 	},
 }
diff --git a/cli/cmd/prompt.go b/cli/cmd/prompt.go
index e9704be94b631c7c17c75e8fa744f8c0ef8ae7f8..20be885d3f62c66c944dbf81f5492af868a640b4 100644
--- a/cli/cmd/prompt.go
+++ b/cli/cmd/prompt.go
@@ -36,21 +36,23 @@ import (
 	"os"
 	"strings"
 
-	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	"code.fbi.h-da.de/danet/gosdn/cli/completer"
+	"code.fbi.h-da.de/danet/gosdn/controller/api"
 	"github.com/c-bata/go-prompt"
 	"github.com/google/uuid"
+	"github.com/openconfig/goyang/pkg/yang"
+	"github.com/pterm/pterm"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
+	"github.com/spf13/viper"
 )
 
-var suggestions []prompt.Suggest
-
 // PromptCompleter provides completion for a device
 type PromptCompleter struct {
-	//NOTE: not too sure about this but for now it should be sufficient
-	deviceID               uuid.UUID
 	yangSchemaCompleterMap map[uuid.UUID]*completer.YangSchemaCompleter
+	currentSuggestions     []prompt.Suggest
+	document               *prompt.Document
+	history                []string
 }
 
 // NewPromptCompleter returns a new promptCompleter
@@ -62,25 +64,35 @@ func NewPromptCompleter() *PromptCompleter {
 
 // Run starts the interactive completion
 func (pc *PromptCompleter) Run() {
-	fmt.Println("Welcome to the interactive mode of gosdnc.")
-	defer fmt.Println("Bye!")
+	title, _ := pterm.DefaultBigText.WithLetters(
+		pterm.NewLettersFromString("go"),
+		pterm.NewLettersFromStringWithStyle("SDN", pterm.NewStyle(pterm.FgCyan)),
+		pterm.NewLettersFromString("c"),
+	).Srender()
+	description := pterm.DefaultBasicText.Sprint("Control your goSDN controller like you've never done it before!")
+	pterm.DefaultCenter.Println(title)
+	pterm.DefaultCenter.Println(description)
 
 	p := prompt.New(
 		executeFunc,
 		pc.cstmCompleter,
 		prompt.OptionTitle("gosdnc-prompt: interactive gosdn CLI"),
 		prompt.OptionPrefix(">>> "),
+		prompt.OptionPrefixTextColor(prompt.Cyan),
 		prompt.OptionCompletionWordSeparator(completer.YangSchemaCompletionSeperator),
 		prompt.OptionShowCompletionAtStart(),
-		prompt.OptionSuggestionBGColor(prompt.DarkBlue),
-		prompt.OptionSuggestionTextColor(prompt.DarkGray),
-		prompt.OptionDescriptionTextColor(prompt.White),
-		prompt.OptionDescriptionBGColor(prompt.DarkGray),
-		prompt.OptionSelectedSuggestionBGColor(prompt.DarkRed),
+		prompt.OptionCompletionOnDown(),
+		prompt.OptionHistory(pc.history),
+		prompt.OptionSuggestionBGColor(prompt.DarkGray),
+		prompt.OptionSuggestionTextColor(prompt.LightGray),
+		prompt.OptionDescriptionTextColor(prompt.DarkGray),
+		prompt.OptionDescriptionBGColor(prompt.LightGray),
+		prompt.OptionSelectedSuggestionBGColor(prompt.Cyan),
 		prompt.OptionSelectedSuggestionTextColor(prompt.DarkGray),
-		prompt.OptionSelectedDescriptionBGColor(prompt.DarkGray),
-		prompt.OptionSelectedDescriptionTextColor(prompt.White),
+		prompt.OptionSelectedDescriptionBGColor(prompt.LightGray),
+		prompt.OptionSelectedDescriptionTextColor(prompt.DarkGray),
 	)
+
 	p.Run()
 }
 
@@ -96,106 +108,231 @@ func executeFunc(s string) {
 	}
 }
 
-func flagVisitor(f *pflag.Flag) {
-	if !f.Hidden {
-		suggestions = append(suggestions, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage})
-	}
-}
-
 func (pc *PromptCompleter) cstmCompleter(d prompt.Document) []prompt.Suggest {
 	// Start with the cobra 'rootCmd' and walk through it
 	// Reference: https://github.com/stromland/cobra-prompt
 	currCmd := rootCmd
-	inputSplit := removeFlagsFromInputSlice(strings.Fields(d.CurrentLine()))
-	if c, _, err := currCmd.Find(inputSplit); err == nil {
+	inputSplit := strings.Fields(d.CurrentLine())
+	inputSplitFiltered, inputFlags := filterFlagSlice(inputSplit)
+	if c, _, err := currCmd.Find(inputSplitFiltered); err == nil {
 		currCmd = c
 	}
 
-	return completionBasedOnCmd(pc, currCmd, inputSplit, d)
+	return completionBasedOnCmd(pc, currCmd, inputSplitFiltered, inputFlags, d)
 }
 
-func removeFlagsFromInputSlice(input []string) []string {
-	r := []string{}
+func filterFlagSlice(input []string) (commandSlice []string, flagSlice []string) {
 	for _, in := range input {
 		if !strings.HasPrefix(in, "--") {
-			r = append(r, in)
+			commandSlice = append(commandSlice, in)
+		} else {
+			flagSlice = append(flagSlice, strings.Split(in, "=")[0])
 		}
 	}
-	return r
+	return commandSlice, flagSlice
 }
 
 func deviceGetCompletion(c *PromptCompleter, d prompt.Document, inputSplit []string) []prompt.Suggest {
-	inputLen := len(inputSplit)
-	if inputLen == 2 || inputLen == 3 {
-		if id, err := uuid.Parse(inputSplit[inputLen-1]); err == nil {
-			if c, ok := c.yangSchemaCompleterMap[id]; ok {
-				return c.Complete(d)
-			}
-			dev, err := pndAdapter.GetDevice(createContextWithAuthorization(), id.String())
-			if err != nil {
-				return []prompt.Suggest{}
-			}
-			sid, err := uuid.Parse(dev[0].GetSbi().GetId())
-			if err != nil {
-				return []prompt.Suggest{}
-			}
-			schemaTree, err := pndAdapter.GetSbiSchemaTree(createContextWithAuthorization(), sid)
-			if err != nil {
-				return []prompt.Suggest{}
-			}
-			c.yangSchemaCompleterMap[id] = completer.NewYangSchemaCompleter(schemaTree["Device"], true)
-			if yc, ok := c.yangSchemaCompleterMap[id]; ok {
-				c.deviceID = id
-				return yc.Complete(d)
-			}
-
+	switch inputLen := len(inputSplit); inputLen {
+	case 2:
+		return c.updateSuggestionsThroughFunc(d, getDevices)
+	case 3:
+		id, err := uuid.Parse(inputSplit[inputLen-1])
+		if err != nil {
+			return c.updateSuggestionsThroughFunc(d, getDevices)
+		}
+		if c, ok := c.yangSchemaCompleterMap[id]; ok {
+			return c.Complete(d)
+		}
+		schemaTree, err := getSchemaTreeForDeviceID(id.String())
+		if err != nil {
 			return []prompt.Suggest{}
 		}
-		if inputLen == 2 || (inputLen == 3 && !(d.GetWordBeforeCursor() == "")) {
-			return prompt.FilterHasPrefix(getDevices(), d.GetWordBeforeCursor(), true)
+		c.yangSchemaCompleterMap[id] = completer.NewYangSchemaCompleter(schemaTree["Device"], true)
+		if yc, ok := c.yangSchemaCompleterMap[id]; ok {
+			return yc.Complete(d)
+		}
+	case 4:
+		if d.GetWordBeforeCursor() == "" || d.GetWordAfterCursor() != "" {
+			return []prompt.Suggest{}
+		}
+		id, err := uuid.Parse(inputSplit[inputLen-2])
+		if err != nil {
+			return c.updateSuggestionsThroughFunc(d, getDevices)
 		}
-	} else {
-		if yc, ok := c.yangSchemaCompleterMap[c.deviceID]; ok {
+		if yc, ok := c.yangSchemaCompleterMap[id]; ok {
 			return yc.Complete(d)
 		}
+	default:
 		return []prompt.Suggest{}
 	}
 	return []prompt.Suggest{}
 }
 
-func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, loaded []prompt.Suggest) []prompt.Suggest {
-	suggestions = []prompt.Suggest{}
-	if len(loaded) > 0 {
-		suggestions = append(suggestions, loaded...)
+func (pc *PromptCompleter) updateSuggestionsThroughFunc(d prompt.Document, fn func() ([]prompt.Suggest, error)) []prompt.Suggest {
+	if pc.currentSuggestions == nil {
+		var err error
+		pc.currentSuggestions, err = fn()
+		if err != nil {
+			return prompt.FilterHasPrefix(pc.currentSuggestions, d.GetWordBeforeCursor(), true)
+		}
 	}
+	return prompt.FilterHasPrefix(pc.currentSuggestions, d.GetWordBeforeCursor(), true)
+}
+
+func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, inputFlags []string, loaded []prompt.Suggest) []prompt.Suggest {
 	if currCmd.HasAvailableFlags() {
-		// it would be possible to always show the inherited flags, but i think
-		// this is currently not necessary.
-		// currCmd.InheritedFlags().VisitAll(flagVisitor)
-		currCmd.LocalFlags().VisitAll(flagVisitor)
+		currCmd.LocalFlags().VisitAll(
+			func(f *pflag.Flag) {
+				if !f.Hidden && !sliceContains(inputFlags, "--"+f.Name) {
+					loaded = append(loaded, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage})
+				}
+			},
+		)
 	}
 
 	for _, cmd := range currCmd.Commands() {
-		suggestions = append(suggestions, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short})
+		loaded = append(loaded, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short})
 	}
-	return prompt.FilterHasPrefix(suggestions, d.GetWordBeforeCursor(), true)
+
+	return prompt.FilterHasPrefix(loaded, d.GetWordBeforeCursor(), true)
 }
 
-func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, d prompt.Document) []prompt.Suggest {
+//nolint
+func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, inputFlags []string, d prompt.Document) []prompt.Suggest {
 	switch cmd {
-	case pndUseCmd, pndGetCmd:
-		return cobraCommandCompletion(cmd, d, getPnds())
+	case pndUseCmd, pndGetCmd, pndRemoveCmd:
+		if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") {
+			suggestions := c.updateSuggestionsThroughFunc(d, getPnds)
+			return cobraCommandCompletion(cmd, d, inputFlags, suggestions)
+		}
 	case commitCmd:
-		return getChangesByType(pnd.ChangeState_CHANGE_STATE_PENDING)
+		if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") {
+			return c.updateSuggestionsThroughFunc(d, getCommitedChanges)
+		}
 	case confirmCmd:
-		return getChangesByType(pnd.ChangeState_CHANGE_STATE_COMMITTED)
+		if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") {
+			return c.updateSuggestionsThroughFunc(d, getConfirmedChanges)
+		}
+	case deviceRemoveCmd:
+		if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") {
+			return c.updateSuggestionsThroughFunc(d, getDevices)
+		}
 	case deviceGetCmd, deviceSetCmd:
 		return deviceGetCompletion(c, d, inputSplit)
 	case deviceShowCmd:
-		return getDevices()
+		devices, err := getDevices()
+		if err != nil {
+			return []prompt.Suggest{}
+		}
+		return devices
+	case deviceCmd, pndCmd, changeCmd:
+		c.currentSuggestions = nil
+		return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{})
 	default:
-		return cobraCommandCompletion(cmd, d, []prompt.Suggest{})
+		return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{})
+	}
+
+	return []prompt.Suggest{}
+}
+
+// getDevices is a helper function which requests devices from the controller
+// and gives feedback about the current pulling status with the help of pterm
+// the result is converted into a prompt.Suggest slice.
+func getDevices() ([]prompt.Suggest, error) {
+	spinner, _ := pterm.DefaultSpinner.Start("Fetching devices from controller.")
+	resp, err := pndAdapter.GetDevices(createContextWithAuthorization())
+	if err != nil {
+		spinner.Fail(err)
+		return []prompt.Suggest{}, err
+	}
+
+	s := []prompt.Suggest{}
+	for _, ond := range resp.Ond {
+		s = append(s, prompt.Suggest{Text: ond.GetId(), Description: ond.GetName()})
+	}
+	spinner.Success()
+	return completer.SortSuggestionByText(s), nil
+}
+
+// getSchemaTreeForDeviceID is a helper function which requests the SBI's
+// schema tree of a specific device. The function gives feedback about the
+// current pulling status with the help of pterm.
+func getSchemaTreeForDeviceID(id string) (map[string]*yang.Entry, error) {
+	spinner, _ := pterm.DefaultSpinner.Start("Fetching schema tree for Device with ID: ", id)
+	dev, err := pndAdapter.GetDevice(createContextWithAuthorization(), id)
+	if err != nil {
+		spinner.Fail(err)
+		return nil, err
+	}
+	sid, err := uuid.Parse(dev.GetOnd().GetSbi().GetId())
+	if err != nil {
+		spinner.Fail(err)
+		return nil, err
+	}
+	spinner.Success()
+	return pndAdapter.GetSbiSchemaTree(createContextWithAuthorization(), sid)
+}
+
+// getPnds is a helper function which requests pnds from the controller and
+// gives feedback about the current pulling status with the help of pterm the
+// result is converted into a prompt.Suggest slice.
+func getPnds() ([]prompt.Suggest, error) {
+	spinner, _ := pterm.DefaultSpinner.Start("Fetching PNDs from controller.")
+	resp, err := api.GetIds(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"))
+	if err != nil {
+		spinner.Fail(err)
+		return []prompt.Suggest{}, err
+	}
+
+	s := []prompt.Suggest{}
+	for _, pnd := range resp {
+		s = append(s, prompt.Suggest{Text: pnd.GetId(), Description: pnd.GetDescription()})
+	}
+	spinner.Success()
+	return completer.SortSuggestionByText(s), nil
+}
+
+// getCommitedChanges is a helper function which requests all the commited
+// changes from the controller and gives feedback about the current pulling
+// status with the help of pterm the result is converted into a prompt.Suggest
+// slice.
+func getCommitedChanges() ([]prompt.Suggest, error) {
+	spinner, _ := pterm.DefaultSpinner.Start("Fetching commited changes.")
+
+	resp, err := pndAdapter.CommittedChanges(createContextWithAuthorization())
+	if err != nil {
+		spinner.Fail(err)
+		return []prompt.Suggest{}, err
+	}
+
+	s := []prompt.Suggest{}
+	for _, change := range resp {
+		s = append(s, prompt.Suggest{Text: change.GetId(), Description: change.State.String()})
+	}
+	spinner.Success()
+	return completer.SortSuggestionByText(s), nil
+}
+
+// getConfirmedChanges is a helper function which requests all the confirmed
+// changes from the controller and gives feedback about the current pulling
+// status with the help of pterm the result is converted into a prompt.Suggest
+// slice.
+func getConfirmedChanges() ([]prompt.Suggest, error) {
+	spinner, _ := pterm.DefaultSpinner.Start("Fetching confirmed changes.")
+
+	resp, err := pndAdapter.ConfirmedChanges(createContextWithAuthorization())
+	if err != nil {
+		spinner.Fail(err)
+		return []prompt.Suggest{}, err
+	}
+
+	s := []prompt.Suggest{}
+	for _, change := range resp {
+		s = append(s, prompt.Suggest{Text: change.GetId(), Description: change.State.String()})
 	}
+	spinner.Success()
+	return completer.SortSuggestionByText(s), nil
 }
 
 var exitCmd = &cobra.Command{
diff --git a/cli/cmd/root.go b/cli/cmd/root.go
index 3fdfffe2095ed8c681896c51683fdde555236579..bf5c804082d791d811db3f991fb88f40ed0ba1ce 100644
--- a/cli/cmd/root.go
+++ b/cli/cmd/root.go
@@ -67,7 +67,8 @@ The login command must be called for authorization.
 // Execute adds all child commands to the root command and sets flags appropriately.
 // This is called by main.main(). It only needs to happen once to the rootCmd.
 func Execute() {
-	cobra.CheckErr(rootCmd.Execute())
+	rootCmd.Execute()
+	//cobra.CheckErr(rootCmd.Execute())
 }
 
 func init() {
diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go
index cf6a0378032e6d3305564603ffb893089c2541d0..0e5df4a663be835a9701806ff9bff5e1d6b07a02 100644
--- a/cli/cmd/utils.go
+++ b/cli/cmd/utils.go
@@ -36,11 +36,6 @@ import (
 	"errors"
 	"net"
 
-	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
-	"code.fbi.h-da.de/danet/gosdn/cli/completer"
-	"code.fbi.h-da.de/danet/gosdn/controller/api"
-	"github.com/c-bata/go-prompt"
-	"github.com/spf13/viper"
 	"google.golang.org/grpc/metadata"
 )
 
@@ -60,45 +55,14 @@ func checkIPPort(string) error {
 	return nil
 }
 
-func getDevices() []prompt.Suggest {
-	resp, err := api.GetDevices(createContextWithAuthorization(), pndAdapter.Endpoint(), pndAdapter.ID().String())
-	if err != nil {
-		return []prompt.Suggest{}
-	}
-
-	s := []prompt.Suggest{}
-	for _, ond := range resp.Ond {
-		s = append(s, prompt.Suggest{Text: ond.GetId(), Description: ond.GetName()})
-	}
-	return completer.SortSuggestionByText(s)
-}
-
-func getPnds() []prompt.Suggest {
-	resp, err := api.GetIds(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"))
-	if err != nil {
-		return []prompt.Suggest{}
-	}
-
-	s := []prompt.Suggest{}
-	for _, pnd := range resp {
-		s = append(s, prompt.Suggest{Text: pnd.GetId(), Description: pnd.GetDescription()})
-	}
-	return completer.SortSuggestionByText(s)
-}
-
-func getChangesByType(cType pnd.ChangeState) []prompt.Suggest {
-	resp, err := api.GetChanges(createContextWithAuthorization(), pndAdapter.Endpoint(), pndAdapter.ID().String())
-	if err != nil {
-		return []prompt.Suggest{}
-	}
-
-	s := []prompt.Suggest{}
-	for _, change := range resp.GetChange() {
-		if change.GetState() == cType {
-			s = append(s, prompt.Suggest{Text: change.GetId(), Description: change.State.String()})
+// sliceContains checks if a slice contains the given item
+func sliceContains[T comparable](slice []T, toCompare T) bool {
+	for _, sliceEntry := range slice {
+		if sliceEntry == toCompare {
+			return true
 		}
 	}
-	return completer.SortSuggestionByText(s)
+	return false
 }
 
 func createContextWithAuthorization() context.Context {
diff --git a/controller/Makefile b/controller/Makefile
index 1ca977f2b730d2b27c1feb07c955291e66a52dd5..fdedd2e7b5ae2d83ed942cd18fe1573a2348c160 100644
--- a/controller/Makefile
+++ b/controller/Makefile
@@ -53,7 +53,7 @@ ci-unit-test: ci-install-tools
 	ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -short -race $$( go list ./... | grep -v /forks/ | grep -v /mocks ) -v -coverprofile=coverage.out
 
 ci-controller-test: ci-install-tools
-	ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -race -v -run TestRun
+	ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -race -v -run TestRun -coverprofile=coverage.out
 
 integration-test-nucleus:
 	ENVIRONMENT=testing  &&\
diff --git a/controller/api/apiIntegration_test.go b/controller/api/apiIntegration_test.go
index 8a288847339ff1ff24aa6388d0cad891b469de3c..a97a54820db061d3e85f91105982bb903c2547cb 100644
--- a/controller/api/apiIntegration_test.go
+++ b/controller/api/apiIntegration_test.go
@@ -86,7 +86,6 @@ func TestApiIntegration(t *testing.T) {
 				context.TODO(),
 				testAPIEndpoint,
 				cliPnd,
-				"",
 				did,
 			)
 			if (err != nil) != tt.wantErr {
@@ -109,7 +108,7 @@ func TestApiIntegration(t *testing.T) {
 				return
 			}
 
-			resp, err := GetDevice(context.TODO(), testAddress, testUsername, testPassword, testPath)
+			resp, err := GetDevice(context.TODO(), testAddress, testUsername, testPassword)
 			if err != nil {
 				if !tt.wantErr {
 					t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
@@ -118,7 +117,7 @@ func TestApiIntegration(t *testing.T) {
 			}
 			var got string
 			if resp != nil {
-				got = resp.Ond[0].Name
+				got = resp.Ond.Name
 			} else {
 				t.Errorf("integration test failed got cannot be nil")
 			}
diff --git a/controller/api/api_test.go b/controller/api/api_test.go
index 0f4f904af2aa7dedc1a393879e137cccf037145e..a789e65b18d39981c98b18b2c2b60219849ff011 100644
--- a/controller/api/api_test.go
+++ b/controller/api/api_test.go
@@ -47,7 +47,7 @@ func Test_GetPnd(t *testing.T) {
 		t.Error(err)
 		return
 	}
-	got := resp.Pnd[0].Id
+	got := resp.Pnd.Id
 	if got != pndID {
 		t.Errorf("PND ID is %v, expected %v", got, pndID)
 	}
@@ -101,7 +101,7 @@ func Test_GetDevice(t *testing.T) {
 		t.Error(err)
 		return
 	}
-	got := resp.Ond[0].Id
+	got := resp.Ond.Id
 	if got != ondID {
 		t.Errorf("PND ID is %v, expected %v", got, ondID)
 	}
diff --git a/controller/api/change.go b/controller/api/change.go
index e469db6c1f584bd139d9f6127b70af7aa74abd39..57b82608554a78c6dd892557b300df9cdd6ee4c1 100644
--- a/controller/api/change.go
+++ b/controller/api/change.go
@@ -2,6 +2,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"time"
 
 	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
@@ -21,6 +22,23 @@ func GetChanges(ctx context.Context, addr, pnd string) (*ppb.GetChangeListRespon
 	return client.GetChangeList(ctx, req)
 }
 
+// GetChange requests one or more changes from the controller
+func GetChange(ctx context.Context, addr string, pnd string, args ...string) (*ppb.GetChangeResponse, error) {
+	client, err := nbi.PndClient(addr, dialOptions...)
+	if err != nil {
+		return nil, err
+	}
+	if len(args) <= 0 {
+		return nil, errors.New("not enough arguments")
+	}
+	req := &ppb.GetChangeRequest{
+		Timestamp: time.Now().UnixNano(),
+		Pid:       pnd,
+		Cuid:      args,
+	}
+	return client.GetChange(ctx, req)
+}
+
 // Commit sends a Commit request for one or multiple changes to the
 // controller.
 func Commit(ctx context.Context, addr, pnd string, cuids ...string) (*ppb.SetChangeListResponse, error) {
@@ -61,9 +79,10 @@ func CommitConfirm(ctx context.Context, addr, pnd string, changes []*ppb.SetChan
 	return client.SetChangeList(ctx, req)
 }
 
-// ChangeRequest change creates a ChangeRequest for the specified OND. ApiOperations are
-// used to specify the type of the change (update, replace, delete as specified
-// in https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#34-modifying-state)
+// ChangeRequest creates a ChangeRequest for the specified OND. ApiOperations
+// are used to specify the type of the change (update, replace, delete as
+// specified in
+// https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#34-modifying-state)
 // For delete operations the value field needs to contain an empty string.
 func ChangeRequest(ctx context.Context, addr, did, pid, path, value string, op ppb.ApiOperation) (*ppb.SetPathListResponse, error) {
 	req := &ppb.ChangeRequest{
diff --git a/controller/api/device.go b/controller/api/device.go
index b8c6a00141d54df49b6db447e549f18fa782e8b2..9ac80f41bf95713d42959155e1dc51c7d161ab58 100644
--- a/controller/api/device.go
+++ b/controller/api/device.go
@@ -52,7 +52,7 @@ func AddDevice(ctx context.Context, addr, deviceName string, opt *tpb.TransportO
 // GetDevice requests one device belonging to a given
 // PrincipalNetworkDomain from the controller. If no device identifier
 // is provided, an error is thrown.
-func GetDevice(ctx context.Context, addr, pid string, did ...string) (*ppb.GetOndResponse, error) {
+func GetDevice(ctx context.Context, addr, pid string, did string) (*ppb.GetOndResponse, error) {
 	pndClient, err := nbi.PndClient(addr, dialOptions...)
 	if err != nil {
 		return nil, err
diff --git a/controller/api/initialise_test.go b/controller/api/initialise_test.go
index 5a8e97231f32e8a287b79ae266424364e93c60b1..bdd70085037ef49cedd18f19aa2ba437871e6405 100644
--- a/controller/api/initialise_test.go
+++ b/controller/api/initialise_test.go
@@ -85,9 +85,26 @@ func bootstrapUnitTest() {
 	userService = rbacImpl.NewUserService(rbacImpl.NewMemoryUserStore())
 	roleService = rbacImpl.NewRoleService(rbacImpl.NewMemoryRoleStore())
 
+	previousHostname := "previousHostname"
+	intendedHostname := "intendedHostname"
+
 	mockChange := &mocks.Change{}
 	mockChange.On("Age").Return(time.Hour)
 	mockChange.On("State").Return(ppb.ChangeState_CHANGE_STATE_INCONSISTENT)
+	mockChange.On("PreviousState").Return(&openconfig.Device{
+		System: &openconfig.OpenconfigSystem_System{
+			Config: &openconfig.OpenconfigSystem_System_Config{
+				Hostname: &previousHostname,
+			},
+		},
+	})
+	mockChange.On("IntendedState").Return(&openconfig.Device{
+		System: &openconfig.OpenconfigSystem_System{
+			Config: &openconfig.OpenconfigSystem_System_Config{
+				Hostname: &intendedHostname,
+			},
+		},
+	})
 
 	mockPnd := mocks.NetworkDomain{}
 	mockPnd.On("ID").Return(pndUUID)
@@ -96,7 +113,7 @@ func bootstrapUnitTest() {
 	mockPnd.On("PendingChanges").Return([]uuid.UUID{changeUUID})
 	mockPnd.On("CommittedChanges").Return([]uuid.UUID{changeUUID})
 	mockPnd.On("GetChange", mock.Anything).Return(mockChange, nil)
-	mockPnd.On("AddDevice", mock.Anything, mock.Anything, mock.Anything).Return(nil)
+	mockPnd.On("AddDevice", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
 	mockPnd.On("GetDevice", mock.Anything).Return(&nucleus.CommonDevice{
 		UUID:  deviceUUID,
 		Model: &openconfig.Device{},
diff --git a/controller/api/pnd.go b/controller/api/pnd.go
index 791ebefc6d425580547364ff7ee28509100938d2..a6c9eb0ac0e9c3eb57d88db980c702fd9ebf7b9e 100644
--- a/controller/api/pnd.go
+++ b/controller/api/pnd.go
@@ -33,7 +33,7 @@ func AddPnd(ctx context.Context, addr, name, description, sbi string) (*pb.Creat
 
 // GetPnd requests one PrincipalNetworkDomain from the
 // controller.
-func GetPnd(ctx context.Context, addr string, args ...string) (*pb.GetPndResponse, error) {
+func GetPnd(ctx context.Context, addr string, args string) (*pb.GetPndResponse, error) {
 	coreClient, err := nbi.CoreClient(addr, dialOptions...)
 	if err != nil {
 		return nil, err
@@ -56,9 +56,6 @@ func GetPnds(ctx context.Context, addr string, args ...string) (*pb.GetPndListRe
 	if err != nil {
 		return nil, err
 	}
-	if len(args) <= 0 {
-		return nil, errors.New("not enough arguments")
-	}
 
 	req := &pb.GetPndListRequest{
 		Timestamp: time.Now().UnixNano(),
diff --git a/controller/api/sbi.go b/controller/api/sbi.go
index 30de02ab087ea5c0698a80d96eaeb76505d26b6f..e34ec6a9d4c61fdbc52dc3876770a7515b7501e2 100644
--- a/controller/api/sbi.go
+++ b/controller/api/sbi.go
@@ -10,7 +10,7 @@ import (
 
 // GetSbi requests one or more to the provided PND belonging SBIs from the
 // controller.
-func GetSbi(ctx context.Context, addr string, pid string, sid ...string) (*ppb.GetSbiResponse, error) {
+func GetSbi(ctx context.Context, addr string, pid string, sid string) (*ppb.GetSbiResponse, error) {
 	client, err := nbi.PndClient(addr, dialOptions...)
 	if err != nil {
 		return nil, err
diff --git a/controller/interfaces/change/change.go b/controller/interfaces/change/change.go
index ba8075db9dd3b7c4f85b872b947a084c8a19f076..40e8cc90ecbba6985a92989ecfeb81f09f265597 100644
--- a/controller/interfaces/change/change.go
+++ b/controller/interfaces/change/change.go
@@ -18,6 +18,8 @@ type Change interface {
 	Confirm() error
 	State() ppb.ChangeState
 	Age() time.Duration
+	PreviousState() ygot.GoStruct
+	IntendedState() ygot.GoStruct
 }
 
 // Payload contains two ygot.GoStructs, the first represents the original state
diff --git a/controller/interfaces/networkdomain/pnd.go b/controller/interfaces/networkdomain/pnd.go
index 2c86f6260acc4da3d2eba8b84688fe659592c68e..fc9dec411c54ec8a1877445401bb801f37aec274 100644
--- a/controller/interfaces/networkdomain/pnd.go
+++ b/controller/interfaces/networkdomain/pnd.go
@@ -16,7 +16,7 @@ type NetworkDomain interface {
 	Destroy() error
 	AddSbi(s southbound.SouthboundInterface) error
 	RemoveSbi(uuid.UUID) error
-	AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) error
+	AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) (uuid.UUID, error)
 	GetDevice(identifier string) (device.Device, error)
 	RemoveDevice(uuid.UUID) error
 	Devices() []device.Device
diff --git a/controller/mocks/Change.go b/controller/mocks/Change.go
index 9c3e9b9f26cddfe94a04c0e0d1a68b8f248dfa3a..fb370384e3fbc8e3ee90bc09e28fbe39cad807e2 100644
--- a/controller/mocks/Change.go
+++ b/controller/mocks/Change.go
@@ -1,14 +1,18 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
 import (
-	time "time"
+	testing "testing"
 
 	pnd "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	mock "github.com/stretchr/testify/mock"
 
+	time "time"
+
 	uuid "github.com/google/uuid"
+
+	ygot "github.com/openconfig/ygot/ygot"
 )
 
 // Change is an autogenerated mock type for the Change type
@@ -74,6 +78,38 @@ func (_m *Change) ID() uuid.UUID {
 	return r0
 }
 
+// IntendedState provides a mock function with given fields:
+func (_m *Change) IntendedState() ygot.GoStruct {
+	ret := _m.Called()
+
+	var r0 ygot.GoStruct
+	if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(ygot.GoStruct)
+		}
+	}
+
+	return r0
+}
+
+// PreviousState provides a mock function with given fields:
+func (_m *Change) PreviousState() ygot.GoStruct {
+	ret := _m.Called()
+
+	var r0 ygot.GoStruct
+	if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(ygot.GoStruct)
+		}
+	}
+
+	return r0
+}
+
 // State provides a mock function with given fields:
 func (_m *Change) State() pnd.ChangeState {
 	ret := _m.Called()
@@ -87,3 +123,12 @@ func (_m *Change) State() pnd.ChangeState {
 
 	return r0
 }
+
+// NewChange creates a new instance of Change. It also registers a cleanup function to assert the mocks expectations.
+func NewChange(t testing.TB) *Change {
+	mock := &Change{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/Device.go b/controller/mocks/Device.go
index 5004309d1d439424d96d31b581b3e5f915d7f3bb..4b42cddd742c8809f09c16d2911ddc6d05f80cd2 100644
--- a/controller/mocks/Device.go
+++ b/controller/mocks/Device.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
@@ -7,6 +7,8 @@ import (
 	mock "github.com/stretchr/testify/mock"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 
+	testing "testing"
+
 	transport "code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport"
 
 	uuid "github.com/google/uuid"
@@ -19,32 +21,32 @@ type Device struct {
 	mock.Mock
 }
 
-// ID provides a mock function with given fields:
-func (_m *Device) ID() uuid.UUID {
+// GetModel provides a mock function with given fields:
+func (_m *Device) GetModel() ygot.ValidatedGoStruct {
 	ret := _m.Called()
 
-	var r0 uuid.UUID
-	if rf, ok := ret.Get(0).(func() uuid.UUID); ok {
+	var r0 ygot.ValidatedGoStruct
+	if rf, ok := ret.Get(0).(func() ygot.ValidatedGoStruct); ok {
 		r0 = rf()
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(uuid.UUID)
+			r0 = ret.Get(0).(ygot.ValidatedGoStruct)
 		}
 	}
 
 	return r0
 }
 
-// Model provides a mock function with given fields:
-func (_m *Device) Model() ygot.GoStruct {
+// ID provides a mock function with given fields:
+func (_m *Device) ID() uuid.UUID {
 	ret := _m.Called()
 
-	var r0 ygot.GoStruct
-	if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok {
+	var r0 uuid.UUID
+	if rf, ok := ret.Get(0).(func() uuid.UUID); ok {
 		r0 = rf()
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(ygot.GoStruct)
+			r0 = ret.Get(0).(uuid.UUID)
 		}
 	}
 
@@ -110,3 +112,12 @@ func (_m *Device) Transport() transport.Transport {
 
 	return r0
 }
+
+// NewDevice creates a new instance of Device. It also registers a cleanup function to assert the mocks expectations.
+func NewDevice(t testing.TB) *Device {
+	mock := &Device{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/NetworkDomain.go b/controller/mocks/NetworkDomain.go
index 607db2834b1e53331278f1cc1ddcb153790f67a8..22e6e7bfc2f65a0316466d46598827dc31eb621c 100644
--- a/controller/mocks/NetworkDomain.go
+++ b/controller/mocks/NetworkDomain.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
@@ -14,6 +14,8 @@ import (
 
 	southbound "code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 
+	testing "testing"
+
 	transport "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
 
 	uuid "github.com/google/uuid"
@@ -25,17 +27,26 @@ type NetworkDomain struct {
 }
 
 // AddDevice provides a mock function with given fields: name, opts, sid
-func (_m *NetworkDomain) AddDevice(name string, opts *transport.TransportOption, sid uuid.UUID) error {
+func (_m *NetworkDomain) AddDevice(name string, opts *transport.TransportOption, sid uuid.UUID) (uuid.UUID, error) {
 	ret := _m.Called(name, opts, sid)
 
-	var r0 error
-	if rf, ok := ret.Get(0).(func(string, *transport.TransportOption, uuid.UUID) error); ok {
+	var r0 uuid.UUID
+	if rf, ok := ret.Get(0).(func(string, *transport.TransportOption, uuid.UUID) uuid.UUID); ok {
 		r0 = rf(name, opts, sid)
 	} else {
-		r0 = ret.Error(0)
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(uuid.UUID)
+		}
 	}
 
-	return r0
+	var r1 error
+	if rf, ok := ret.Get(1).(func(string, *transport.TransportOption, uuid.UUID) error); ok {
+		r1 = rf(name, opts, sid)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
 }
 
 // AddSbi provides a mock function with given fields: s
@@ -393,3 +404,12 @@ func (_m *NetworkDomain) RequestAll(_a0 string) error {
 
 	return r0
 }
+
+// NewNetworkDomain creates a new instance of NetworkDomain. It also registers a cleanup function to assert the mocks expectations.
+func NewNetworkDomain(t testing.TB) *NetworkDomain {
+	mock := &NetworkDomain{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/Plugin.go b/controller/mocks/Plugin.go
index f69729e0c9536a06314fca0e65d3f9b56157af3c..b6d86b9165866a110766c87bbd51b7d8934f3108 100644
--- a/controller/mocks/Plugin.go
+++ b/controller/mocks/Plugin.go
@@ -1,11 +1,14 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
 import (
+	testing "testing"
+
 	plugin "code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
-	uuid "github.com/google/uuid"
 	mock "github.com/stretchr/testify/mock"
+
+	uuid "github.com/google/uuid"
 )
 
 // Plugin is an autogenerated mock type for the Plugin type
@@ -86,3 +89,12 @@ func (_m *Plugin) Update() error {
 
 	return r0
 }
+
+// NewPlugin creates a new instance of Plugin. It also registers a cleanup function to assert the mocks expectations.
+func NewPlugin(t testing.TB) *Plugin {
+	mock := &Plugin{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/SouthboundInterface.go b/controller/mocks/SouthboundInterface.go
index abf903d86ecce202e3a6c11b27e4098220e0afc5..ca8fa0a15e5db5baad513f82c4b2398c26eb120c 100644
--- a/controller/mocks/SouthboundInterface.go
+++ b/controller/mocks/SouthboundInterface.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
@@ -7,6 +7,8 @@ import (
 	gnmi "github.com/openconfig/gnmi/proto/gnmi"
 	mock "github.com/stretchr/testify/mock"
 
+	testing "testing"
+
 	uuid "github.com/google/uuid"
 
 	yang "github.com/openconfig/goyang/pkg/yang"
@@ -143,3 +145,12 @@ func (_m *SouthboundInterface) Unmarshal(_a0 []byte, _a1 *gnmi.Path, _a2 ygot.Va
 
 	return r0
 }
+
+// NewSouthboundInterface creates a new instance of SouthboundInterface. It also registers a cleanup function to assert the mocks expectations.
+func NewSouthboundInterface(t testing.TB) *SouthboundInterface {
+	mock := &SouthboundInterface{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/Storable.go b/controller/mocks/Storable.go
index 2f37e9dc922e617f2b42e0a89903d1001c1042c8..9219bcfc00e0276434dcc8cb53dbaa8a0cfddb18 100644
--- a/controller/mocks/Storable.go
+++ b/controller/mocks/Storable.go
@@ -1,10 +1,12 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
 import (
 	mock "github.com/stretchr/testify/mock"
 
+	testing "testing"
+
 	uuid "github.com/google/uuid"
 )
 
@@ -28,3 +30,12 @@ func (_m *Storable) ID() uuid.UUID {
 
 	return r0
 }
+
+// NewStorable creates a new instance of Storable. It also registers a cleanup function to assert the mocks expectations.
+func NewStorable(t testing.TB) *Storable {
+	mock := &Storable{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/Transport.go b/controller/mocks/Transport.go
index b2c7aa34f6b2b4235d36f407c9ed7c24f1ffd940..ae80536a4f465db7af6e5d47ec8beebd7ee027c4 100644
--- a/controller/mocks/Transport.go
+++ b/controller/mocks/Transport.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.10.0. DO NOT EDIT.
+// Code generated by mockery v2.11.0. DO NOT EDIT.
 
 package mocks
 
@@ -9,6 +9,8 @@ import (
 
 	mock "github.com/stretchr/testify/mock"
 
+	testing "testing"
+
 	ytypes "github.com/openconfig/ygot/ytypes"
 )
 
@@ -109,3 +111,12 @@ func (_m *Transport) Type() string {
 
 	return r0
 }
+
+// NewTransport creates a new instance of Transport. It also registers a cleanup function to assert the mocks expectations.
+func NewTransport(t testing.TB) *Transport {
+	mock := &Transport{}
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/northbound/server/auth_test.go b/controller/northbound/server/auth_test.go
index ba6487644fe11d68577783a293b11016ae4a325b..8681ca7cb016d73c9ffcb9859a36be747655229d 100644
--- a/controller/northbound/server/auth_test.go
+++ b/controller/northbound/server/auth_test.go
@@ -620,6 +620,7 @@ func TestAuth_UpdateRoles(t *testing.T) {
 }
 
 func TestAuth_DeletePermissionsForRole(t *testing.T) {
+	clearAndCreateAuthTestSetup()
 	type args struct {
 		ctx     context.Context
 		request *apb.DeletePermissionsForRoleRequest
diff --git a/controller/northbound/server/core.go b/controller/northbound/server/core.go
index d002ded24df4cc088af9d432aeffb0095d1ce0ad..13a7304c5975738d97f543a7f02f6452c25da171 100644
--- a/controller/northbound/server/core.go
+++ b/controller/northbound/server/core.go
@@ -22,27 +22,25 @@ func (s core) GetPnd(ctx context.Context, request *pb.GetPndRequest) (*pb.GetPnd
 	start := metrics.StartHook(labels, grpcRequestsTotal)
 	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
 
-	pndList, err := stringToUUID(request.Pid)
+	pndID, err := uuid.Parse(request.Pid)
 	if err != nil {
 		return nil, handleRPCError(labels, err)
 	}
 
-	pnds := make([]*ppb.PrincipalNetworkDomain, len(pndList))
-	for i, id := range pndList {
-		pnd, err := pndc.Get(store.Query{ID: id})
-		if err != nil {
-			return nil, err
-		}
+	storedPnd, err := pndc.Get(store.Query{ID: pndID})
+	if err != nil {
+		return nil, err
+	}
 
-		pnds[i] = &ppb.PrincipalNetworkDomain{
-			Id:          pnd.ID().String(),
-			Name:        pnd.GetName(),
-			Description: pnd.GetDescription(),
-		}
+	pnd := &ppb.PrincipalNetworkDomain{
+		Id:          storedPnd.ID().String(),
+		Name:        storedPnd.GetName(),
+		Description: storedPnd.GetDescription(),
 	}
+
 	return &pb.GetPndResponse{
 		Timestamp: time.Now().UnixNano(),
-		Pnd:       pnds,
+		Pnd:       pnd,
 	}, nil
 }
 
diff --git a/controller/northbound/server/core_test.go b/controller/northbound/server/core_test.go
index 86a36afc739716c1bbac9f1306edb60e368debdc..ba01c8c4c930d12f0a80fc71e3ee89f568205aff 100644
--- a/controller/northbound/server/core_test.go
+++ b/controller/northbound/server/core_test.go
@@ -66,7 +66,6 @@ func Test_core_GetPnd(t *testing.T) {
 		name    string
 		args    args
 		want    []string
-		length  int
 		wantErr bool
 	}{
 		{
@@ -74,12 +73,9 @@ func Test_core_GetPnd(t *testing.T) {
 			args: args{
 				ctx: context.Background(),
 				request: &pb.GetPndRequest{
-					Pid: []string{
-						pndID,
-					},
+					Pid: pndID,
 				},
 			},
-			length: 1,
 			want: []string{
 				pndID,
 				"test",
@@ -87,6 +83,7 @@ func Test_core_GetPnd(t *testing.T) {
 			},
 		},
 	}
+
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			s := core{
@@ -100,18 +97,14 @@ func Test_core_GetPnd(t *testing.T) {
 
 			if tt.name == "default" {
 				got := []string{
-					resp.Pnd[0].Id,
-					resp.Pnd[0].Name,
-					resp.Pnd[0].Description,
+					resp.Pnd.Id,
+					resp.Pnd.Name,
+					resp.Pnd.Description,
 				}
 				if !reflect.DeepEqual(got, tt.want) {
 					t.Errorf("core.GetPnd() = %v, want %v", got, tt.want)
 				}
 			}
-			length := len(resp.Pnd)
-			if tt.length != length {
-				t.Errorf("core.GetPnd() = %v, want %v", length, tt.length)
-			}
 		})
 	}
 }
diff --git a/controller/northbound/server/pnd.go b/controller/northbound/server/pnd.go
index 6d53008450b78c502f81a6bf5ace70a8c367d0c4..fbd7e730879d7e3a5b55229729a9ef49dee45f9a 100644
--- a/controller/northbound/server/pnd.go
+++ b/controller/northbound/server/pnd.go
@@ -42,7 +42,7 @@ func (p pndServer) GetOnd(ctx context.Context, request *ppb.GetOndRequest) (*ppb
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
 	}
-	onds, err := fillOnds(pnd, false, request.Did...)
+	onds, err := fillOnd(pnd, request.Did)
 	if err != nil {
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
@@ -72,7 +72,7 @@ func (p pndServer) GetOndList(ctx context.Context, request *ppb.GetOndListReques
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
 	}
-	onds, err := fillOnds(pnd, true)
+	onds, err := fillOnds(pnd)
 	if err != nil {
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
@@ -88,58 +88,50 @@ func (p pndServer) GetOndList(ctx context.Context, request *ppb.GetOndListReques
 	}, nil
 }
 
-func fillOnds(pnd networkdomain.NetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) {
-	var ondList []device.Device
-	var onds []*ppb.OrchestratedNetworkingDevice
+func fillOnd(pnd networkdomain.NetworkDomain, did string) (*ppb.OrchestratedNetworkingDevice, error) {
+	d, err := pnd.GetDevice(did)
+	if err != nil {
+		log.Error(err)
+		return nil, status.Errorf(codes.Aborted, "%v", err)
+	}
+	cfg := ygot.GNMINotificationsConfig{}
+	dev, err := ygot.TogNMINotifications(d.GetModel(), time.Now().UnixNano(), cfg)
+	if err != nil {
+		log.Error(err)
+		return nil, status.Errorf(codes.Aborted, "%v", err)
+	}
 
-	// all indicates if a client wants all devices or only a single one
-	switch all {
-	case true:
-		ondList = pnd.Devices()
-		onds = make([]*ppb.OrchestratedNetworkingDevice, len(ondList))
-		for _, dev := range ondList {
-			did = append(did, dev.ID().String())
-		}
+	sbi := spb.SouthboundInterface{}
+	if d.SBI() != nil {
+		sbi.Id = d.SBI().ID().String()
+		sbi.Type = d.SBI().Type()
+	}
 
-	default:
-		if len(did) == 0 {
-			err := &errors.ErrInvalidParameters{
-				Func:  fillOnds,
-				Param: "length of 'did' cannot be '0' when 'all' is set to 'false'",
-			}
-			log.Error(err)
+	return &ppb.OrchestratedNetworkingDevice{
+		Id:     did,
+		Name:   d.Name(),
+		Device: dev,
+		Sbi:    &sbi,
+	}, nil
+}
 
-			return nil, err
-		}
+func fillOnds(pnd networkdomain.NetworkDomain) ([]*ppb.OrchestratedNetworkingDevice, error) {
+	var ondList []device.Device
+	var onds []*ppb.OrchestratedNetworkingDevice
+
+	ondList = pnd.Devices()
+	var did []string
 
-		onds = make([]*ppb.OrchestratedNetworkingDevice, 1)
+	for _, dev := range ondList {
+		did = append(did, dev.ID().String())
 	}
 
-	for i, id := range did {
-		d, err := pnd.GetDevice(id)
+	for _, id := range did {
+		ond, err := fillOnd(pnd, id)
 		if err != nil {
-			log.Error(err)
-			return nil, status.Errorf(codes.Aborted, "%v", err)
-		}
-		cfg := ygot.GNMINotificationsConfig{}
-		dev, err := ygot.TogNMINotifications(d.GetModel(), time.Now().UnixNano(), cfg)
-		if err != nil {
-			log.Error(err)
-			return nil, status.Errorf(codes.Aborted, "%v", err)
-		}
-
-		sbi := spb.SouthboundInterface{}
-		if d.SBI() != nil {
-			sbi.Id = d.SBI().ID().String()
-			sbi.Type = d.SBI().Type()
-		}
-
-		onds[i] = &ppb.OrchestratedNetworkingDevice{
-			Id:     id,
-			Name:   d.Name(),
-			Device: dev,
-			Sbi:    &sbi,
+			return nil, err
 		}
+		onds = append(onds, ond)
 	}
 
 	return onds, nil
@@ -253,7 +245,13 @@ func (p pndServer) GetSbi(ctx context.Context, request *ppb.GetSbiRequest) (*ppb
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
 	}
-	sbis, err := fillSbis(pnd, false, request.Sid...)
+
+	sbiID, err := uuid.Parse(request.Sid)
+	if err != nil {
+		return nil, err
+	}
+
+	sbi, err := pnd.GetSBI(sbiID)
 	if err != nil {
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
@@ -265,7 +263,10 @@ func (p pndServer) GetSbi(ctx context.Context, request *ppb.GetSbiRequest) (*ppb
 			Name:        pnd.GetName(),
 			Description: pnd.GetDescription(),
 		},
-		Sbi: sbis,
+		Sbi: &spb.SouthboundInterface{
+			Id:   sbiID.String(),
+			Type: sbi.Type(),
+		},
 	}, nil
 }
 
@@ -283,7 +284,7 @@ func (p pndServer) GetSbiList(ctx context.Context, request *ppb.GetSbiListReques
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
 	}
-	sbis, err := fillSbis(pnd, true, "")
+	sbis, err := fillSbis(pnd)
 	if err != nil {
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
@@ -299,7 +300,7 @@ func (p pndServer) GetSbiList(ctx context.Context, request *ppb.GetSbiListReques
 	}, nil
 }
 
-func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) {
+func fillSbis(pnd networkdomain.NetworkDomain) ([]*spb.SouthboundInterface, error) {
 	sbis, err := pnd.GetSBIs()
 	if err != nil {
 		return nil, err
@@ -320,7 +321,7 @@ func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.
 	return sbisToReturn, nil
 }
 
-func stringToUUID(sid []string) ([]uuid.UUID, error) {
+func stringArrayToUUIDs(sid []string) ([]uuid.UUID, error) {
 	UUIDs := make([]uuid.UUID, len(sid))
 	for i, id := range sid {
 		parsed, err := uuid.Parse(id)
@@ -393,7 +394,7 @@ func (p pndServer) GetChange(ctx context.Context, request *ppb.GetChangeRequest)
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
 	}
-	changes, err := fillChanges(pnd, false, request.Cuid)
+	changes, err := fillChanges(pnd, false, request.Cuid...)
 	if err != nil {
 		log.Error(err)
 		return nil, status.Errorf(codes.Aborted, "%v", err)
@@ -454,7 +455,7 @@ func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]*
 				Param: "length of 'did' cannot be '0' when 'all' is set to 'false'",
 			}
 		}
-		changeList, err = stringToUUID(cuid)
+		changeList, err = stringArrayToUUIDs(cuid)
 		if err != nil {
 			log.Error(err)
 			return nil, status.Errorf(codes.Aborted, "%v", err)
@@ -469,10 +470,17 @@ func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]*
 			return nil, status.Errorf(codes.Aborted, "%v", err)
 		}
 
+		diff, err := ygot.Diff(c.PreviousState(), c.IntendedState())
+		if err != nil {
+			log.Error(err)
+			return nil, status.Errorf(codes.Aborted, "%v", err)
+		}
+
 		changes[i] = &ppb.Change{
 			Id:    ch.String(),
 			Age:   c.Age().Microseconds(),
 			State: c.State(),
+			Diff:  diff,
 		}
 	}
 	return changes, nil
@@ -492,25 +500,30 @@ func (p pndServer) SetOndList(ctx context.Context, request *ppb.SetOndListReques
 		return nil, handleRPCError(labels, err)
 	}
 
+	deviceIDs := make([]uuid.UUID, 0, len(request.Ond))
 	for _, r := range request.Ond {
 		sid, err := uuid.Parse(r.Sbi.Id)
 		if err != nil {
 			log.Error(err)
 			return nil, status.Errorf(codes.Aborted, "%v", err)
 		}
-		if err := pnd.AddDevice(r.DeviceName, r.TransportOption, sid); err != nil {
+		did, err := pnd.AddDevice(r.DeviceName, r.TransportOption, sid)
+		if err != nil {
 			log.Error(err)
 			return nil, status.Errorf(codes.Aborted, "%v", err)
 		}
+		deviceIDs = append(deviceIDs, did)
 	}
+
+	r := make([]*ppb.SetResponse, len(deviceIDs))
+	for i, did := range deviceIDs {
+		r[i] = &ppb.SetResponse{Id: did.String(), Status: ppb.Status_STATUS_OK}
+	}
+
 	return &ppb.SetOndListResponse{
 		Timestamp: time.Now().UnixNano(),
 		Status:    ppb.Status_STATUS_OK,
-		Responses: []*ppb.SetResponse{
-			{
-				Status: ppb.Status_STATUS_OK,
-			},
-		},
+		Responses: r,
 	}, nil
 }
 
diff --git a/controller/northbound/server/pnd_test.go b/controller/northbound/server/pnd_test.go
index ca3ac203213824532d41742be4cd061228756883..be7622913b8ff9d8ae57dd99443cade4be8fd56b 100644
--- a/controller/northbound/server/pnd_test.go
+++ b/controller/northbound/server/pnd_test.go
@@ -180,19 +180,18 @@ func Test_pnd_Get(t *testing.T) {
 			args: args{
 				ctx: context.Background(),
 				request: &pb.GetPndRequest{
-					Pid: []string{
-						pndID},
+					Pid: pndID,
 				},
 			},
 			want: &pb.GetPndResponse{
-				Pnd: []*ppb.PrincipalNetworkDomain{
-					{Id: pndID,
-						Name:        "test",
-						Description: "test"},
-				},
+				Pnd: &ppb.PrincipalNetworkDomain{
+					Id:          pndID,
+					Name:        "test",
+					Description: "test"},
 			},
 		},
 	}
+
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := core{
diff --git a/controller/nucleus/change.go b/controller/nucleus/change.go
index 6da303875849d7a9f6e27f3f4f8904f3f043845d..935360ca57c77ff157f40168cff8c0c44dfc78da 100644
--- a/controller/nucleus/change.go
+++ b/controller/nucleus/change.go
@@ -116,6 +116,18 @@ func (c *Change) State() ppb.ChangeState {
 	return state
 }
 
+// PreviousState returns the previous state of the devices config as
+// ygot.GoStruct.
+func (c *Change) PreviousState() ygot.GoStruct {
+	return c.previousState
+}
+
+// IntendedState returns the intended state of the devices config as
+// ygot.GoStruct.
+func (c *Change) IntendedState() ygot.GoStruct {
+	return c.intendedState
+}
+
 func stateManager(ctx context.Context, ch *Change, timeout time.Duration) (chan<- ppb.ChangeState, <-chan ppb.ChangeState, <-chan error) {
 	stateIn := make(chan ppb.ChangeState)
 	stateOut := make(chan ppb.ChangeState)
diff --git a/controller/nucleus/memoryDeviceStore.go b/controller/nucleus/memoryDeviceStore.go
index 536bb6ea4502e5de931b31e3ae95a25c514dda62..9a04d7a5c1c3fa06648e1eddefe7c2156ce35dcd 100644
--- a/controller/nucleus/memoryDeviceStore.go
+++ b/controller/nucleus/memoryDeviceStore.go
@@ -49,8 +49,8 @@ func (t *MemoryDeviceStore) Add(item device.Device) error {
 // Update updates a existing device.
 func (t *MemoryDeviceStore) Update(item device.Device) error {
 	_, ok := t.Store[item.ID().String()]
-	if ok {
-		return nil
+	if !ok {
+		return errors.ErrCouldNotFind{StoreName: deviceStoreName}
 	}
 
 	var device device.LoadedDevice
diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go
index 69795871e51da7d81d867d1a817dc6aca8413963..b3499a8d8a5bf09c35f9d6093f73be3b386a0a8b 100644
--- a/controller/nucleus/principalNetworkDomain.go
+++ b/controller/nucleus/principalNetworkDomain.go
@@ -215,32 +215,31 @@ func (pnd *pndImplementation) RemoveSbi(sid uuid.UUID) error {
 }
 
 // AddDevice adds a new device to the PND
-func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, sid uuid.UUID) error {
+func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, sid uuid.UUID) (uuid.UUID, error) {
 	labels := prometheus.Labels{"type": opt.Type.String()}
 	start := metrics.StartHook(labels, deviceCreationsTotal)
 	defer metrics.FinishHook(labels, start, deviceCreationDurationSecondsTotal, deviceCreationDurationSeconds)
 	var sbi southbound.SouthboundInterface
+	var err error
 
 	switch t := opt.Type; t {
 	case spb.Type_TYPE_CONTAINERISED:
 		return pnd.handleCsbiEnrolment(name, opt)
 	case spb.Type_TYPE_PLUGIN:
-		var err error
 		sbi, err = pnd.requestPlugin(name, opt)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 	default:
-		var err error
 		sbi, err = pnd.sbic.Get(store.Query{ID: sid})
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 	}
 
 	d, err := NewDevice(name, uuid.Nil, opt, sbi)
 	if err != nil {
-		return err
+		return uuid.Nil, err
 	}
 	return pnd.addDevice(d)
 }
@@ -302,13 +301,13 @@ func (pnd *pndImplementation) removeSbi(id uuid.UUID) error {
 }
 
 // addDevice adds a device to the PND's device store.
-func (pnd *pndImplementation) addDevice(device device.Device) error {
+func (pnd *pndImplementation) addDevice(device device.Device) (uuid.UUID, error) {
 	err := pnd.devices.Add(device)
 	if err != nil {
-		return err
+		return uuid.Nil, err
 	}
 
-	return nil
+	return device.ID(), nil
 }
 
 func (pnd *pndImplementation) removeDevice(id uuid.UUID) error {
@@ -492,7 +491,7 @@ func (pnd *pndImplementation) handleCsbiDeletion(id uuid.UUID) error {
 	return nil
 }
 
-func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.TransportOption) error {
+func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.TransportOption) (uuid.UUID, error) {
 	g := new(errgroup.Group)
 	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
 	defer cancel()
@@ -502,20 +501,26 @@ func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.Transpor
 	}
 	resp, err := pnd.csbiClient.Create(ctx, req)
 	if err != nil {
-		return err
+		return uuid.Nil, err
 	}
+	// the slice only contains one deployment
+	var devID uuid.UUID
 	for _, d := range resp.Deployments {
 		dCopy := d
 		g.Go(func() error {
-			return pnd.createCsbiDevice(ctx, name, dCopy, opt)
+			devID, err = pnd.createCsbiDevice(ctx, name, dCopy, opt)
+			if err != nil {
+				return err
+			}
+			return nil
 		})
 	}
 	err = g.Wait()
 	if err != nil {
-		return err
+		return uuid.Nil, err
 	}
 
-	return nil
+	return devID, nil
 }
 
 // createCsbiDevice is a helper method for cSBI device creation. The method
@@ -526,10 +531,10 @@ func (pnd *pndImplementation) createCsbiDevice(
 	name string,
 	d *cpb.Deployment,
 	opt *tpb.TransportOption,
-) error {
+) (uuid.UUID, error) {
 	id, err := uuid.Parse(d.Id)
 	if err != nil {
-		return err
+		return uuid.Nil, err
 	}
 	ch := make(chan device.Details, 1)
 	pnd.callback(id, ch)
@@ -547,7 +552,7 @@ func (pnd *pndImplementation) createCsbiDevice(
 		log.Infof("syn from csbi %v", deviceDetails.ID)
 		id, err := uuid.Parse(deviceDetails.ID)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		csbiTransportOptions := &tpb.TransportOption{
 			Address:         deviceDetails.Address,
@@ -568,41 +573,42 @@ func (pnd *pndImplementation) createCsbiDevice(
 		// here and in csbi.
 		gClient, err := pnd.csbiClient.GetGoStruct(ctx, req)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		csbiID, err := saveGenericClientStreamToFile(gClient, "gostructs.go", uuid.New())
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		// TODO: this is currently just a workaround needs major adjustments
 		// here and in csbi.
 		mClient, err := pnd.csbiClient.GetManifest(ctx, req)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		_, err = saveGenericClientStreamToFile(mClient, "plugin.yml", csbiID)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		csbi, err := NewSBI(spb.Type_TYPE_CONTAINERISED, csbiID)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		err = pnd.sbic.Add(csbi)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		d, err := NewDevice(name, uuid.Nil, csbiTransportOptions, csbi)
 		if err != nil {
-			return err
+			return uuid.Nil, err
 		}
 		d.(*CsbiDevice).UUID = id
 		ch <- device.Details{TransportOption: opt}
 		if err := pnd.devices.Add(d); err != nil {
-			return err
+			return uuid.Nil, err
 		}
+		return id, nil
 	}
-	return nil
+	return uuid.Nil, nil
 }
 
 // requestPlugin is a feature for cSBIs and sends a plugin request to the cSBI
diff --git a/controller/nucleus/principalNetworkDomain_test.go b/controller/nucleus/principalNetworkDomain_test.go
index f06f7cfc791de08f35133317a23ef43a750312bf..a70b61252633e51e37cd6e6c249ff01fef733e9b 100644
--- a/controller/nucleus/principalNetworkDomain_test.go
+++ b/controller/nucleus/principalNetworkDomain_test.go
@@ -115,7 +115,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 				t.Error(err)
 			}
 
-			err := pnd.AddDevice(tt.args.name, tt.args.opts, defaultSbiID)
+			_, err := pnd.AddDevice(tt.args.name, tt.args.opts, defaultSbiID)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
 			}
@@ -290,7 +290,8 @@ func Test_pndImplementation_MarshalDevice(t *testing.T) {
 				sbi:       sbi,
 				transport: nil,
 			}
-			if err := pnd.addDevice(d); err != nil {
+			_, err = pnd.addDevice(d)
+			if err != nil {
 				t.Error(err)
 			}
 			got, err := pnd.MarshalDevice(tt.args.uuid.String())
@@ -339,7 +340,8 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) {
 				sbi:       sbi,
 				transport: nil,
 			}
-			if err := pnd.addDevice(d); err != nil {
+			_, err = pnd.addDevice(d)
+			if err != nil {
 				t.Error(err)
 			}
 			if err := pnd.RemoveDevice(tt.args.uuid); (err != nil) != tt.wantErr {
@@ -454,10 +456,12 @@ func Test_pndImplementation_RemoveSbiWithAssociatedDevices(t *testing.T) {
 			if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil {
 				t.Error(err)
 			}
-			if err := pnd.AddDevice("associatedDevice", opts, tt.args.id); err != nil {
+			_, err = pnd.AddDevice("associatedDevice", opts, tt.args.id)
+			if err != nil {
 				t.Error(err)
 			}
-			if err := pnd.AddDevice("associatedDevice2", opts, tt.args.id); err != nil {
+			_, err = pnd.AddDevice("associatedDevice2", opts, tt.args.id)
+			if err != nil {
 				t.Error(err)
 			}
 			if tt.name == "exclusively remove associated devices" {
@@ -465,7 +469,8 @@ func Test_pndImplementation_RemoveSbiWithAssociatedDevices(t *testing.T) {
 				if err := pnd.addSbi(&OpenConfig{id: newID}); err != nil {
 					t.Error(err)
 				}
-				if err := pnd.AddDevice("associatedDevice2", opts, newID); err != nil {
+				_, err := pnd.AddDevice("associatedDevice2", opts, newID)
+				if err != nil {
 					t.Error(err)
 				}
 			}
@@ -560,7 +565,7 @@ func Test_pndImplementation_Request(t *testing.T) {
 				transport: &transport,
 			}
 
-			_ = pnd.addDevice(deviceWithMockTransport)
+			_, _ = pnd.addDevice(deviceWithMockTransport)
 
 			_, err = pnd.Request(tt.args.uuid, tt.args.path)
 			if (err != nil) != tt.wantErr {
@@ -644,7 +649,7 @@ func Test_pndImplementation_RequestAll(t *testing.T) {
 				transport: &transport,
 			}
 
-			_ = pnd.addDevice(deviceWithMockTransport)
+			_, _ = pnd.addDevice(deviceWithMockTransport)
 
 			device, _ := pnd.devices.Get(store.Query{ID: mdid})
 			if device == nil {
@@ -756,7 +761,8 @@ func Test_pndImplementation_ChangeOND(t *testing.T) {
 			if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil {
 				t.Error(err)
 			}
-			if err := pnd.AddDevice("testdevice", opts, defaultSbiID); err != nil {
+			_, err := pnd.AddDevice("testdevice", opts, defaultSbiID)
+			if err != nil {
 				t.Error(err)
 				return
 			}
@@ -799,7 +805,8 @@ func Test_pndImplementation_GetDevice(t *testing.T) {
 		t.Error(err)
 		return
 	}
-	if err = pnd.addDevice(d); err != nil {
+	_, err = pnd.addDevice(d)
+	if err != nil {
 		t.Error(err)
 		return
 	}
@@ -859,7 +866,8 @@ func Test_pndImplementation_GetDeviceByName(t *testing.T) {
 		t.Error(err)
 		return
 	}
-	if err = pnd.addDevice(d); err != nil {
+	_, err = pnd.addDevice(d)
+	if err != nil {
 		t.Error(err)
 		return
 	}
@@ -933,11 +941,12 @@ func Test_pndImplementation_Confirm(t *testing.T) {
 			d := mockDevice()
 			tr := d.Transport().(*mocks.Transport)
 			tr.On("Set", mockContext, mock.Anything, mock.Anything).Return(nil)
-			if err := pnd.addDevice(d); err != nil {
+			_, err := pnd.addDevice(d)
+			if err != nil {
 				t.Error(err)
 				return
 			}
-			_, err := pnd.ChangeOND(d.ID(), ppb.ApiOperation_API_OPERATION_UPDATE, "system/config/hostname", "ceos3000")
+			_, err = pnd.ChangeOND(d.ID(), ppb.ApiOperation_API_OPERATION_UPDATE, "system/config/hostname", "ceos3000")
 			if err != nil {
 				t.Error(err)
 				return
diff --git a/controller/rbac/memoryRoleStore.go b/controller/rbac/memoryRoleStore.go
index e40dc60b79afde6cecb0a69e9586f140fe74fbd9..da0e023eb7ffb6c14bb1ec1a4211603aadde82d6 100644
--- a/controller/rbac/memoryRoleStore.go
+++ b/controller/rbac/memoryRoleStore.go
@@ -55,8 +55,8 @@ func (s *MemoryRoleStore) Delete(item rbac.Role) error {
 // Update updates an existing role.
 func (s *MemoryRoleStore) Update(item rbac.Role) error {
 	_, ok := s.Store[item.ID().String()]
-	if ok {
-		return nil
+	if !ok {
+		return errors.ErrCouldNotFind{StoreName: roleStoreName}
 	}
 
 	var role rbac.LoadedRole
diff --git a/controller/rbac/memoryUserStore.go b/controller/rbac/memoryUserStore.go
index 338f56180fe137187b9c12a95530bf5a1caf5d46..c97439278b59716ee188f635c178e94eb8d6efd2 100644
--- a/controller/rbac/memoryUserStore.go
+++ b/controller/rbac/memoryUserStore.go
@@ -55,8 +55,8 @@ func (s *MemoryUserStore) Delete(item rbac.User) error {
 // Update updates an existing user.
 func (s *MemoryUserStore) Update(item rbac.User) error {
 	_, ok := s.Store[item.ID().String()]
-	if ok {
-		return nil
+	if !ok {
+		return errors.ErrCouldNotFind{StoreName: userStoreName}
 	}
 
 	var user rbac.LoadedUser
diff --git a/controller/test/integration/nucleusIntegration_test.go b/controller/test/integration/nucleusIntegration_test.go
index 04899ccee07a31faf95e180cee1ffaf9df8ca386..333efb1778f6acf0a22cc9f54f9ed57e82d150bc 100644
--- a/controller/test/integration/nucleusIntegration_test.go
+++ b/controller/test/integration/nucleusIntegration_test.go
@@ -177,7 +177,8 @@ func TestGnmi_SetValidIntegration(t *testing.T) {
 		t.Error(err)
 		return
 	}
-	if err := pnd.AddDevice("test", opt, sbi.ID()); err != nil {
+	_, err = pnd.AddDevice("test", opt, sbi.ID())
+	if err != nil {
 		t.Error(err)
 		return
 	}
diff --git a/go.mod b/go.mod
index b35ed07e1023f269be5f4b6b0771ac6c8cfe66b6..ae34105ad3b70e38c2fdcf51fed055822ce50d07 100644
--- a/go.mod
+++ b/go.mod
@@ -25,6 +25,7 @@ require (
 require (
 	github.com/c-bata/go-prompt v0.2.6
 	github.com/mitchellh/go-homedir v1.1.0
+	github.com/pterm/pterm v0.12.41
 	github.com/spf13/pflag v1.0.5
 	go.mongodb.org/mongo-driver v1.8.4
 	google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3
@@ -37,6 +38,14 @@ require (
 
 require github.com/gorilla/mux v1.8.0 // indirect
 
+require (
+	github.com/atomicgo/cursor v0.0.1 // indirect
+	github.com/gookit/color v1.5.0 // indirect
+	github.com/rivo/uniseg v0.2.0 // indirect
+	github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
+	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
+)
+
 require (
 	github.com/Microsoft/go-winio v0.5.1 // indirect
 	github.com/Microsoft/hcsshim v0.9.2 // indirect
@@ -63,7 +72,7 @@ require (
 	github.com/magiconair/properties v1.8.5 // indirect
 	github.com/mattn/go-colorable v0.1.7 // indirect
 	github.com/mattn/go-isatty v0.0.12 // indirect
-	github.com/mattn/go-runewidth v0.0.9 // indirect
+	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/mattn/go-tty v0.0.3 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
 	github.com/mitchellh/mapstructure v1.4.2 // indirect
diff --git a/go.sum b/go.sum
index 269d78c6602a33845743b3e80481a478e9d9014a..6871178105715d93874ff49bc76dc8e93cd07bc3 100644
--- a/go.sum
+++ b/go.sum
@@ -70,6 +70,14 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
+github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
+github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
+github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k=
+github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
+github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
+github.com/MarvinJWendt/testza v0.3.5 h1:g9krITRRlIsF1eO9sUKXtiTw670gZIIk6T08Keeo1nM=
+github.com/MarvinJWendt/testza v0.3.5/go.mod h1:ExbTpWmA1z2E9HSskvrNcwApoX4F9bID692s10nuHRY=
 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
@@ -118,6 +126,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU=
+github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
 github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
 github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
 github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -509,6 +519,9 @@ github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pf
 github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
 github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
 github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
+github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
+github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
+github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
 github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@@ -599,6 +612,10 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
 github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
 github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
+github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
+github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -640,8 +657,9 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
 github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
 github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
@@ -827,6 +845,17 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
+github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
+github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
+github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=
+github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
+github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
+github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
+github.com/pterm/pterm v0.12.41 h1:e2BRfFo1H9nL8GY0S3ImbZqfZ/YimOk9XtkhoobKJVs=
+github.com/pterm/pterm v0.12.41/go.mod h1:LW/G4J2A42XlTaPTAGRPvbBfF4UXvHWhC6SN7ueU4jU=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -841,6 +870,8 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
 github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI=
 github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@@ -936,6 +967,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
@@ -1250,15 +1283,19 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
 golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=