Repository: apigee/registry
Pull request #378 (2021-10-29 23:42:43)

Deployment resource implementation
This adds a full implementation of deployment resource support - thanks @seaneganx for a solid set of spec tests that were easy to adapt to debug and verify the deployments implementation.


Patch:
diff --git a/google/cloud/apigeeregistry/v1/registry_service.proto b/google/cloud/apigeeregistry/v1/registry_service.proto
index d3f0328..7e60931 100644
--- a/google/cloud/apigeeregistry/v1/registry_service.proto
+++ b/google/cloud/apigeeregistry/v1/registry_service.proto
@@ -903,6 +903,10 @@ message UpdateApiDeploymentRequest {
   // If a "*" is specified, all fields are updated, including fields that are
   // unspecified/default in the request.
   google.protobuf.FieldMask update_mask = 2;
+
+  // If set to true, and the deployment is not found, a new deployment will be created.
+  // In this situation, `update_mask` is ignored.
+  bool allow_missing = 3;
 }
 
 // Request message for DeleteApiDeployment.
diff --git a/rpc/registry_service.pb.go b/rpc/registry_service.pb.go
index 395d3db..4419ed8 100644
--- a/rpc/registry_service.pb.go
+++ b/rpc/registry_service.pb.go
@@ -1829,6 +1829,9 @@ type UpdateApiDeploymentRequest struct {
 	// If a "*" is specified, all fields are updated, including fields that are
 	// unspecified/default in the request.
 	UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
+	// If set to true, and the deployment is not found, a new deployment will be created.
+	// In this situation, `update_mask` is ignored.
+	AllowMissing bool `protobuf:"varint,3,opt,name=allow_missing,json=allowMissing,proto3" json:"allow_missing,omitempty"`
 }
 
 func (x *UpdateApiDeploymentRequest) Reset() {
@@ -1877,6 +1880,13 @@ func (x *UpdateApiDeploymentRequest) GetUpdateMask() *fieldmaskpb.FieldMask {
 	return nil
 }
 
+func (x *UpdateApiDeploymentRequest) GetAllowMissing() bool {
+	if x != nil {
+		return x.AllowMissing
+	}
+	return false
+}
+
 // Request message for DeleteApiDeployment.
 type DeleteApiDeploymentRequest struct {
 	state         protoimpl.MessageState
@@ -2923,7 +2933,7 @@ var file_google_cloud_apigeeregistry_v1_registry_service_proto_rawDesc = []byte{
 	0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x11, 0x61, 0x70, 0x69, 0x5f,
 	0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
 	0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0f, 0x61, 0x70, 0x69, 0x44, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xb4, 0x01, 0x0a, 0x1a, 0x55, 0x70,
+	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xd9, 0x01, 0x0a, 0x1a, 0x55, 0x70,
 	0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
 	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f,
 	0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
@@ -2935,675 +2945,677 @@ var file_google_cloud_apigeeregistry_v1_registry_service_proto_rawDesc = []byte{
 	0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
 	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64,
 	0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b,
-	0x22, 0x65, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xe0, 0x41,
-	0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e,
-	0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
-	0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x1f, 0x54, 0x61, 0x67, 0x41,
-	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69,
-	0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xe0, 0x41, 0x02, 0xfa, 0x41,
-	0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04,
-	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xa8, 0x01, 0x0a, 0x21,
-	0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
-	0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x47, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
-	0x33, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
-	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70,
-	0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
-	0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61,
-	0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70,
-	0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f,
-	0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67,
-	0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa4, 0x01, 0x0a, 0x22, 0x4c, 0x69, 0x73, 0x74, 0x41,
-	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a,
-	0x0f, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73,
-	0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f,
-	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x61, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
-	0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61,
-	0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
-	0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8d, 0x01,
-	0x0a, 0x1c, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xe0, 0x41,
-	0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e,
-	0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
-	0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0b, 0x72, 0x65, 0x76, 0x69, 0x73,
-	0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41,
-	0x02, 0x52, 0x0a, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x6d, 0x0a,
-	0x22, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
-	0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e,
+	0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4d, 0x69,
+	0x73, 0x73, 0x69, 0x6e, 0x67, 0x22, 0x65, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41,
+	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
 	0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
 	0x09, 0x42, 0x33, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65,
 	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
 	0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
-	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xb2, 0x01, 0x0a,
-	0x14, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x12, 0x26, 0x61,
-	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72, 0x74,
-	0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a,
-	0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
-	0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61,
-	0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
-	0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c,
-	0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65,
-	0x72, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
-	0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x61,
-	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
-	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
-	0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
-	0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65,
-	0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65,
-	0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x58, 0x0a, 0x12, 0x47,
-	0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
-	0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x0a, 0x26, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
-	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70,
-	0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52,
-	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x60, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69,
-	0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x0a, 0x26, 0x61, 0x70, 0x69, 0x67, 0x65,
-	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61,
-	0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x46, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x12, 0x26, 0x61, 0x70, 0x69, 0x67, 0x65,
-	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x61, 0x72, 0x74,
-	0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f,
+	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x81, 0x01, 0x0a,
+	0x1f, 0x54, 0x61, 0x67, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
+	0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x47, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33,
+	0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69,
+	0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d,
+	0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x61, 0x67,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x03, 0x74, 0x61, 0x67,
+	0x22, 0xa8, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
+	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70,
+	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44,
+	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+	0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
+	0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa4, 0x01, 0x0a, 0x22,
+	0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
+	0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79,
+	0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f,
 	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
-	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74,
-	0x69, 0x66, 0x61, 0x63, 0x74, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69,
-	0x66, 0x61, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0a,
-	0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x22, 0x63, 0x0a, 0x16, 0x52, 0x65,
-	0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x22,
-	0x5b, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69,
+	0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x61, 0x70, 0x69, 0x44,
+	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65,
+	0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b,
+	0x65, 0x6e, 0x22, 0x8d, 0x01, 0x0a, 0x1c, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41,
+	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x42, 0x33, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
+	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0b,
+	0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0a, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+	0x49, 0x64, 0x22, 0x6d, 0x0a, 0x22, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44,
+	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2d, 0x0a, 0x2b,
+	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x70,
+	0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x22, 0xb2, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x06, 0x70, 0x61,
+	0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa,
+	0x41, 0x28, 0x12, 0x26, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f,
+	0x6d, 0x2f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12,
+	0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16,
+	0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+	0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41,
+	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x46, 0x0a, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
+	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x09, 0x61,
+	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74,
+	0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
+	0x22, 0x58, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x0a, 0x26, 0x61, 0x70,
+	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72, 0x74, 0x69,
+	0x66, 0x61, 0x63, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x60, 0x0a, 0x1a, 0x47, 0x65,
+	0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+	0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x0a, 0x26,
 	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67,
 	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72,
-	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x8f, 0x45, 0x0a,
-	0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x12, 0xa8, 0x01, 0x0a, 0x08, 0x4c, 0x69,
-	0x73, 0x74, 0x41, 0x70, 0x69, 0x73, 0x12, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x73,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67,
-	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69,
-	0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02,
-	0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70,
-	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x70, 0x69, 0x73, 0xda, 0x41, 0x06, 0x70, 0x61,
-	0x72, 0x65, 0x6e, 0x74, 0x12, 0x95, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x12,
-	0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd0, 0x01, 0x0a,
+	0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x12, 0x26,
+	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x49,
+	0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
+	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
+	0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52,
+	0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03,
+	0xe0, 0x41, 0x02, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x22,
+	0x63, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x61, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69,
+	0x66, 0x61, 0x63, 0x74, 0x22, 0x5b, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02,
+	0xfa, 0x41, 0x28, 0x0a, 0x26, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x32, 0x8f, 0x45, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x12, 0xa8,
+	0x01, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x73, 0x12, 0x2f, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
+	0x74, 0x41, 0x70, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67,
+	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x73, 0x74, 0x41, 0x70, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39,
+	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72,
+	0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x70, 0x69, 0x73,
+	0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x95, 0x01, 0x0a, 0x06, 0x47, 0x65,
+	0x74, 0x41, 0x70, 0x69, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
+	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a,
+	0x12, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0xad, 0x01, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x12,
+	0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
 	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
-	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
-	0x41, 0x70, 0x69, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31,
+	0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
+	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
+	0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x22, 0x49, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x28,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x3a, 0x03, 0x61, 0x70, 0x69, 0xda, 0x41, 0x11,
+	0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70, 0x69, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x69,
+	0x64, 0x12, 0xaf, 0x01, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x12,
+	0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
+	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
+	0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
+	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
+	0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x32, 0x2c,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
+	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x03, 0x61, 0x70,
+	0x69, 0xda, 0x41, 0x0f, 0x61, 0x70, 0x69, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d,
+	0x61, 0x73, 0x6b, 0x12, 0x8e, 0x01, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70,
+	0x69, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
+	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
+	0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4,
+	0x93, 0x02, 0x2a, 0x2a, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70,
+	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x12, 0xc8, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69,
+	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70,
+	0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
+	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
+	0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x35, 0x12, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70,
+	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x76, 0x65,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12,
+	0xb5, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+	0x6e, 0x12, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
+	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
+	0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67,
+	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x76, 0x31,
 	0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
 	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70,
-	0x69, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xad, 0x01, 0x0a,
-	0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65,
-	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
-	0x74, 0x65, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67,
+	0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d,
+	0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xe5, 0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61,
+	0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x67,
 	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67,
-	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70,
-	0x69, 0x22, 0x49, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
+	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+	0x6e, 0x22, 0x6c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x42, 0x22, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
 	0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
-	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61,
-	0x70, 0x69, 0x73, 0x3a, 0x03, 0x61, 0x70, 0x69, 0xda, 0x41, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e,
-	0x74, 0x2c, 0x61, 0x70, 0x69, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x69, 0x64, 0x12, 0xaf, 0x01, 0x0a,
-	0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65,
-	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61,
-	0x74, 0x65, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67,
-	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70,
-	0x69, 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x32, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
-	0x61, 0x70, 0x69, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70,
+	0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x0b,
+	0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xda, 0x41, 0x21, 0x70, 0x61,
+	0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x2c, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12,
+	0xe7, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
+	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41,
+	0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x4e, 0x32, 0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
 	0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f,
-	0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x03, 0x61, 0x70, 0x69, 0xda, 0x41, 0x0f, 0x61,
-	0x70, 0x69, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0x8e,
-	0x01, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x12, 0x30, 0x2e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67,
-	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
-	0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-	0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x37, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x2a, 0x28,
-	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
-	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
-	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0xc8, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x12, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
-	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
-	0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
-	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
-	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0xb5, 0x01, 0x0a, 0x0d, 0x47,
-	0x65, 0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x2e, 0x67,
+	0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
+	0x2a, 0x7d, 0x3a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xda,
+	0x41, 0x17, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x75, 0x70,
+	0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0xa7, 0x01, 0x0a, 0x10, 0x44, 0x65,
+	0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37,
+	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
+	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
+	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22,
+	0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x2a, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61,
+	0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a,
+	0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x12, 0xc7, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x73, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65,
+	0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+	0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
+	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41,
+	0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
+	0x4c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x12, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61,
+	0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
+	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73,
+	0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73,
+	0x70, 0x65, 0x63, 0x73, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0xb4, 0x01,
+	0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x12, 0x31, 0x2e, 0x67,
 	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67,
 	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
-	0x74, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
-	0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
-	0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x42,
-	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d,
-	0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0xe5, 0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69,
-	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67,
-	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41,
-	0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
-	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
-	0x31, 0x2e, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x82, 0xd3,
-	0xe4, 0x93, 0x02, 0x42, 0x22, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e,
-	0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d,
-	0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xda, 0x41, 0x21, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c,
-	0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x61, 0x70, 0x69, 0x5f,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12, 0xe7, 0x01, 0x0a, 0x10, 0x55,
-	0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
-	0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
-	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
-	0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
-	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72,
-	0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x32, 0x3f, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x6e,
-	0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
-	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
-	0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x0b, 0x61,
-	0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xda, 0x41, 0x17, 0x61, 0x70, 0x69,
-	0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f,
-	0x6d, 0x61, 0x73, 0x6b, 0x12, 0xa7, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41,
-	0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
-	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
-	0x65, 0x41, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93,
-	0x02, 0x35, 0x2a, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
-	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xc7,
-	0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x73, 0x12,
-	0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
+	0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
 	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x73, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
-	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
-	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65,
-	0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x82, 0xd3, 0xe4, 0x93,
-	0x02, 0x3d, 0x12, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d,
+	0x2e, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d,
+	0x12, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x12, 0xbd, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x39, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
+	0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x56, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x49, 0x12, 0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d,
 	0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
 	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65,
-	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0xda,
-	0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0xb4, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74,
-	0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67,
-	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x53,
-	0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65,
-	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x53,
-	0x70, 0x65, 0x63, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x12, 0x3b, 0x2f, 0x76, 0x31,
-	0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
-	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70,
-	0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f,
-	0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0xbd, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f,
-	0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x39, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a,
+	0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xda, 0x41, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x12, 0xdb, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41,
+	0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x12, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
 	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70,
-	0x65, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48,
-	0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x56, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x49, 0x12,
-	0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
-	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74,
-	0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0xdb, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65,
-	0x63, 0x12, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
-	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
-	0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67,
-	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63,
-	0x22, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70,
-	0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69,
-	0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f,
-	0x73, 0x70, 0x65, 0x63, 0x73, 0x3a, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0xda,
-	0x41, 0x1b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65,
-	0x63, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x69, 0x64, 0x12, 0xdd, 0x01,
-	0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x12,
-	0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
-	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
-	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
-	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x6d,
-	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x32, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x70, 0x69,
-	0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70,
+	0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67,
+	0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70,
+	0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x3b, 0x2f,
+	0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
 	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
 	0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x70,
-	0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0xda, 0x41, 0x14, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65,
-	0x63, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0xa9, 0x01,
-	0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x12,
-	0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
-	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x4a, 0x82,
-	0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x2a, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
-	0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f,
-	0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xcc, 0x01, 0x0a, 0x12, 0x54, 0x61,
-	0x67, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
-	0x12, 0x39, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
-	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
-	0x31, 0x2e, 0x54, 0x61, 0x67, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69,
-	0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
-	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69,
-	0x53, 0x70, 0x65, 0x63, 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4c, 0x22, 0x47, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73,
-	0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
-	0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
-	0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x74, 0x61, 0x67, 0x52, 0x65, 0x76,
-	0x69, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0xe4, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73,
-	0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x12, 0x3b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
-	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65,
-	0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
-	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x51, 0x82, 0xd3,
-	0xe4, 0x93, 0x02, 0x4b, 0x12, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d,
+	0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x3a, 0x08, 0x61, 0x70, 0x69, 0x5f,
+	0x73, 0x70, 0x65, 0x63, 0xda, 0x41, 0x1b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70,
+	0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f,
+	0x69, 0x64, 0x12, 0xdd, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69,
+	0x53, 0x70, 0x65, 0x63, 0x12, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65,
+	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x22, 0x6d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x32, 0x44, 0x2f, 0x76, 0x31,
+	0x2f, 0x7b, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d,
 	0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
 	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65,
 	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a,
-	0x7d, 0x3a, 0x6c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12,
-	0xc3, 0x01, 0x0a, 0x0f, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x70, 0x69, 0x53,
-	0x70, 0x65, 0x63, 0x12, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x70, 0x69,
-	0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
-	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69,
-	0x53, 0x70, 0x65, 0x63, 0x22, 0x4f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x49, 0x22, 0x44, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73,
-	0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
-	0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
-	0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
-	0x63, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0xd9, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
-	0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12,
-	0x3c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
-	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65,
-	0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
-	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41,
-	0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x59, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4c, 0x2a, 0x4a,
-	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
-	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
-	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73,
-	0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x64, 0x65, 0x6c, 0x65,
-	0x74, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x12, 0xd4, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x39, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
-	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70,
-	0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
-	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
-	0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61,
-	0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
-	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73,
-	0x2f, 0x2a, 0x7d, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0xda,
-	0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0xc1, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74,
-	0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x37, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
-	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47,
-	0x65, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f,
-	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x45, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f,
-	0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
-	0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f,
-	0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
-	0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xfa, 0x01, 0x0a,
-	0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
-	0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x7d, 0x3a, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0xda, 0x41, 0x14, 0x61, 0x70,
+	0x69, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61,
+	0x73, 0x6b, 0x12, 0xa9, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69,
+	0x53, 0x70, 0x65, 0x63, 0x12, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
 	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
-	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44,
-	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
+	0x74, 0x79, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x2a, 0x3b, 0x2f, 0x76, 0x31, 0x2f,
+	0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
+	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69,
+	0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73,
+	0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xcc,
+	0x01, 0x0a, 0x12, 0x54, 0x61, 0x67, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76,
+	0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x67, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65,
+	0x63, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
 	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
-	0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22,
-	0x78, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x22, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61,
-	0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
+	0x31, 0x2e, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x4c, 0x22, 0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69,
+	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x74,
+	0x61, 0x67, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0xe4, 0x01,
+	0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76,
+	0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
+	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
+	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63,
+	0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x51, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x12, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
+	0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
 	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73,
-	0x2f, 0x2a, 0x7d, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3a,
-	0x0e, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0xda,
-	0x41, 0x27, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c,
-	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x12, 0xfc, 0x01, 0x0a, 0x13, 0x55, 0x70,
-	0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
-	0x74, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
-	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
-	0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
-	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
-	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41,
-	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x7a, 0x82, 0xd3,
-	0xe4, 0x93, 0x02, 0x57, 0x32, 0x45, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x70, 0x69, 0x5f, 0x64,
-	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70,
-	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x0e, 0x61, 0x70, 0x69,
-	0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0xda, 0x41, 0x1a, 0x61, 0x70,
-	0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x75, 0x70, 0x64,
-	0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0xb0, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x6c,
-	0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74,
-	0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
+	0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70,
+	0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x6c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x12, 0xc3, 0x01, 0x0a, 0x0f, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63,
+	0x6b, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x12, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
+	0x63, 0x6b, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
 	0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76,
-	0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f,
-	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
-	0x6d, 0x70, 0x74, 0x79, 0x22, 0x45, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x2a, 0x36, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73,
-	0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
-	0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74,
-	0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xd9, 0x01, 0x0a, 0x18,
-	0x54, 0x61, 0x67, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74,
-	0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x31, 0x2e, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x4f, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x49, 0x22, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69,
+	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x72,
+	0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0xd9, 0x01, 0x0a, 0x15, 0x44,
+	0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69,
+	0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x53,
+	0x70, 0x65, 0x63, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
+	0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x53, 0x70, 0x65, 0x63, 0x22, 0x59, 0x82, 0xd3, 0xe4,
+	0x93, 0x02, 0x4c, 0x2a, 0x4a, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70,
+	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d,
+	0x3a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0xda,
+	0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xd4, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x41,
+	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x39, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
+	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+	0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74,
+	0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
 	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
-	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x67, 0x41, 0x70, 0x69,
-	0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69,
-	0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70,
+	0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x76,
+	0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
+	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d,
+	0x65, 0x6e, 0x74, 0x73, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0xc1, 0x01,
+	0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65,
+	0x6e, 0x74, 0x12, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
+	0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
+	0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69,
+	0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x45, 0x82, 0xd3, 0xe4, 0x93,
+	0x02, 0x38, 0x12, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
+	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c,
+	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0xfa, 0x01, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44,
+	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
 	0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
-	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65,
-	0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x4d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47,
-	0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
-	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
-	0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79,
-	0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x74, 0x61, 0x67, 0x52, 0x65, 0x76, 0x69,
-	0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0xf1, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74,
-	0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76,
-	0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
+	0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
+	0x6d, 0x65, 0x6e, 0x74, 0x22, 0x78, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x22, 0x36, 0x2f, 0x76,
+	0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
+	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d,
+	0x65, 0x6e, 0x74, 0x73, 0x3a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79,
+	0x6d, 0x65, 0x6e, 0x74, 0xda, 0x41, 0x27, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70,
+	0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x70, 0x69,
+	0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x12, 0xfc,
+	0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
+	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
 	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44,
-	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f,
-	0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x42, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
-	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41,
-	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x82,
-	0xd3, 0xe4, 0x93, 0x02, 0x46, 0x12, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
+	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70,
+	0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
+	0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
+	0x74, 0x22, 0x7a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x57, 0x32, 0x45, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
+	0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x6e,
+	0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
+	0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d,
+	0x3a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74,
+	0xda, 0x41, 0x1a, 0x61, 0x70, 0x69, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
+	0x74, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0xb0, 0x01,
+	0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f,
+	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69,
+	0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x45, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x38, 0x2a, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f,
+	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x12, 0xd9, 0x01, 0x0a, 0x18, 0x54, 0x61, 0x67, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f,
+	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
+	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x54,
+	0x61, 0x67, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52,
+	0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d,
+	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
+	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
+	0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x4d, 0x82,
+	0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
 	0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61,
 	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64,
-	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x6c, 0x69,
-	0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xd0, 0x01, 0x0a, 0x15,
-	0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f,
-	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
-	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
-	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41,
-	0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65,
-	0x6e, 0x74, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x22, 0x3f, 0x2f, 0x76, 0x31, 0x2f,
+	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x74, 0x61,
+	0x67, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0xf1, 0x01, 0x0a,
+	0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65,
+	0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
+	0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65,
+	0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x42,
+	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
+	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
+	0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
+	0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x22, 0x4c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x46, 0x12, 0x44, 0x2f, 0x76, 0x31, 0x2f,
 	0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
 	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69,
 	0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f,
-	0x2a, 0x7d, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0xe6,
-	0x01, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
-	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42,
+	0x2a, 0x7d, 0x3a, 0x6c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73,
+	0x12, 0xd0, 0x01, 0x0a, 0x15, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x70, 0x69,
+	0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65,
+	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c,
+	0x62, 0x61, 0x63, 0x6b, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70,
+	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x22,
+	0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
+	0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d,
+	0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
+	0x3a, 0x01, 0x2a, 0x12, 0xe6, 0x01, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70,
+	0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73,
+	0x69, 0x6f, 0x6e, 0x12, 0x42, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
+	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65,
+	0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67,
+	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c,
+	0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x2a, 0x45,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
+	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65,
+	0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x76,
+	0x69, 0x73, 0x69, 0x6f, 0x6e, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xca, 0x03, 0x0a,
+	0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x34,
 	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70,
 	0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e,
-	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d,
-	0x65, 0x6e, 0x74, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
-	0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
-	0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e,
-	0x74, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x2a, 0x45, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
-	0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
-	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73,
-	0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a,
-	0x7d, 0x3a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
-	0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xca, 0x03, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74,
-	0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
-	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41,
-	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
-	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xcb, 0x02, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xbb, 0x02,
-	0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72,
-	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+	0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
+	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xcb, 0x02, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0xbb, 0x02, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66,
+	0x61, 0x63, 0x74, 0x73, 0x5a, 0x36, 0x12, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72,
+	0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
+	0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5a, 0x41, 0x12, 0x3f,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
 	0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5a,
-	0x36, 0x12, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70,
+	0x49, 0x12, 0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70,
 	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72,
-	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5a, 0x41, 0x12, 0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
-	0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
-	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70,
-	0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d,
-	0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5a, 0x49, 0x12, 0x47, 0x2f, 0x76,
+	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d,
+	0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5a, 0x44, 0x12, 0x42, 0x2f, 0x76,
 	0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
 	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
-	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73,
-	0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69,
-	0x66, 0x61, 0x63, 0x74, 0x73, 0x5a, 0x44, 0x12, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61,
-	0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
-	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73,
-	0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a,
-	0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0xda, 0x41, 0x06, 0x70, 0x61,
-	0x72, 0x65, 0x6e, 0x74, 0x12, 0xb7, 0x03, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69,
-	0x66, 0x61, 0x63, 0x74, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c,
-	0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
-	0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
-	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
-	0x63, 0x74, 0x22, 0xc9, 0x02, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xbb, 0x02, 0x12, 0x2d, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73,
-	0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
-	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x36, 0x12, 0x34, 0x2f,
+	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65,
+	0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73,
+	0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0xb7, 0x03, 0x0a, 0x0b, 0x47, 0x65,
+	0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+	0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72,
+	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
+	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41,
+	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x22, 0xc9, 0x02, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xbb,
+	0x02, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d,
+	0x5a, 0x36, 0x12, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
+	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69,
+	0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x41, 0x12, 0x3f, 0x2f, 0x76, 0x31, 0x2f,
+	0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
+	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69,
+	0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
+	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x49, 0x12, 0x47, 0x2f,
 	0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
 	0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f,
-	0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73,
-	0x2f, 0x2a, 0x7d, 0x5a, 0x41, 0x12, 0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
-	0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
-	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x49, 0x12, 0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e,
+	0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
+	0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x44, 0x12, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e,
 	0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
 	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
-	0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65,
-	0x63, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x7d, 0x5a, 0x44, 0x12, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70,
-	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70,
-	0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66,
-	0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0xef,
-	0x03, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f,
-	0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
-	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66,
-	0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e,
-	0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x85, 0x03, 0x82, 0xd3, 0xe4, 0x93, 0x02,
-	0xf7, 0x02, 0x12, 0x39, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
-	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x42, 0x12,
-	0x40, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
-	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
-	0x73, 0x5a, 0x4d, 0x12, 0x4b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70,
-	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73,
-	0x5a, 0x55, 0x12, 0x53, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
+	0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
+	0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x12, 0xef, 0x03, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66,
+	0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65,
+	0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
+	0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x85, 0x03,
+	0x82, 0xd3, 0xe4, 0x93, 0x02, 0xf7, 0x02, 0x12, 0x39, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61,
+	0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+	0x74, 0x73, 0x5a, 0x42, 0x12, 0x40, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d,
+	0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f,
+	0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x4d, 0x12, 0x4b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e,
+	0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
+	0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e,
+	0x74, 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x55, 0x12, 0x53, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61,
+	0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a,
+	0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63,
+	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d,
+	0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x50, 0x12, 0x4e,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+	0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
+	0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65,
+	0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f,
+	0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xda, 0x41,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x86, 0x04, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+	0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+	0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61,
+	0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31,
+	0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x22, 0x92, 0x03, 0x82, 0xd3, 0xe4, 0x93,
+	0x02, 0xed, 0x02, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
+	0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+	0x74, 0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x40, 0x22, 0x34,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66,
+	0x61, 0x63, 0x74, 0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x4b,
+	0x22, 0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72,
 	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
 	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
-	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65, 0x74, 0x43,
-	0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x50, 0x12, 0x4e, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
-	0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f,
-	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73,
-	0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a,
-	0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x67, 0x65,
-	0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-	0x12, 0x86, 0x04, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66,
-	0x61, 0x63, 0x74, 0x12, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66,
+	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+	0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x53, 0x22, 0x47, 0x2f,
+	0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
+	0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+	0x5a, 0x4e, 0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d,
+	0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65,
+	0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+	0xda, 0x41, 0x1b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x2c, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x12, 0xa2,
+	0x04, 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x12, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
+	0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66,
 	0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x6f, 0x6f,
 	0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65,
 	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69,
-	0x66, 0x61, 0x63, 0x74, 0x22, 0x92, 0x03, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xed, 0x02, 0x22, 0x2d,
-	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
-	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
-	0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a, 0x08, 0x61,
-	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x40, 0x22, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
-	0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
+	0x66, 0x61, 0x63, 0x74, 0x22, 0xac, 0x03, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x9a, 0x03, 0x1a, 0x36,
+	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x6e, 0x61,
+	0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+	0x5a, 0x49, 0x1a, 0x3d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+	0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
 	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70,
-	0x69, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a,
-	0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x4b, 0x22, 0x3f, 0x2f, 0x76, 0x31,
-	0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
-	0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f,
-	0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a, 0x08, 0x61, 0x72,
-	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x53, 0x22, 0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70,
-	0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69,
-	0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73,
-	0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x4e, 0x22, 0x42, 0x2f,
-	0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
-	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d,
-	0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x73, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0xda, 0x41, 0x1b, 0x70, 0x61,
-	0x72, 0x65, 0x6e, 0x74, 0x2c, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2c, 0x61, 0x72,
-	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x12, 0xa2, 0x04, 0x0a, 0x0f, 0x52, 0x65,
-	0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x36, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69,
-	0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52,
-	0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
-	0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73,
-	0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x22,
-	0xac, 0x03, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x9a, 0x03, 0x1a, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x7b,
-	0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72,
-	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x49, 0x1a, 0x3d, 0x2f,
+	0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a,
+	0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x54, 0x1a, 0x48, 0x2f,
 	0x76, 0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x6e, 0x61, 0x6d,
 	0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63,
 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f,
-	0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x72,
-	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x54, 0x1a, 0x48, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61,
-	0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f,
-	0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f,
-	0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x5c, 0x1a, 0x50,
-	0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x6e, 0x61,
-	0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a,
-	0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63,
-	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d,
-	0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a, 0x57, 0x1a, 0x4b, 0x2f, 0x76,
-	0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65,
-	0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64,
-	0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74,
-	0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66,
-	0x61, 0x63, 0x74, 0xda, 0x41, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0xab,
-	0x03, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x12, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
-	0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
-	0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
-	0x22, 0xc9, 0x02, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xbb, 0x02, 0x2a, 0x2d, 0x2f, 0x76, 0x31, 0x2f,
-	0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74,
-	0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x36, 0x2a, 0x34, 0x2f, 0x76, 0x31,
+	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66,
+	0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+	0x74, 0x5a, 0x5c, 0x1a, 0x50, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73,
+	0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
+	0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a,
+	0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+	0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5a,
+	0x57, 0x1a, 0x4b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+	0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a,
+	0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69,
+	0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f,
+	0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x08,
+	0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0xda, 0x41, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66,
+	0x61, 0x63, 0x74, 0x12, 0xab, 0x03, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
+	0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+	0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xc9, 0x02, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xbb, 0x02, 0x2a,
+	0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
+	0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x36,
+	0x2a, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+	0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x41, 0x2a, 0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e,
+	0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
+	0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74,
+	0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x49, 0x2a, 0x47, 0x2f, 0x76, 0x31,
 	0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f,
 	0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70,
-	0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a,
-	0x7d, 0x5a, 0x41, 0x2a, 0x3f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70,
-	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
-	0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x49, 0x2a, 0x47, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d,
+	0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f,
+	0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+	0x73, 0x2f, 0x2a, 0x7d, 0x5a, 0x44, 0x2a, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d,
 	0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63,
 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73,
-	0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x5a,
-	0x44, 0x2a, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f,
-	0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x65, 0x70, 0x6c, 0x6f,
-	0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
-	0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x20, 0xca, 0x41,
-	0x1d, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x42, 0x60,
-	0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x22, 0x67, 0x69,
-	0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x2f,
-	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x3b, 0x72, 0x70, 0x63,
-	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x72,
+	0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x1a, 0x20, 0xca, 0x41, 0x1d, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65, 0x67, 0x69,
+	0x73, 0x74, 0x72, 0x79, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e,
+	0x63, 0x6f, 0x6d, 0x42, 0x60, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x67, 0x65, 0x65, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
+	0x01, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70,
+	0x69, 0x67, 0x65, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x72, 0x70,
+	0x63, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/server/registry/actions_deployment_revisions.go b/server/registry/actions_deployment_revisions.go
new file mode 100644
index 0000000..fd46cea
--- /dev/null
+++ b/server/registry/actions_deployment_revisions.go
@@ -0,0 +1,207 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package registry
+
+import (
+	"context"
+
+	"github.com/apigee/registry/rpc"
+	"github.com/apigee/registry/server/registry/internal/storage"
+	"github.com/apigee/registry/server/registry/internal/storage/models"
+	"github.com/apigee/registry/server/registry/names"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// ListApiDeploymentRevisions handles the corresponding API request.
+func (s *RegistryServer) ListApiDeploymentRevisions(ctx context.Context, req *rpc.ListApiDeploymentRevisionsRequest) (*rpc.ListApiDeploymentRevisionsResponse, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	if req.GetPageSize() < 0 {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid page_size %d: must not be negative", req.GetPageSize())
+	} else if req.GetPageSize() > 1000 {
+		req.PageSize = 1000
+	} else if req.GetPageSize() == 0 {
+		req.PageSize = 50
+	}
+
+	parent, err := names.ParseDeployment(req.GetName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	listing, err := db.ListDeploymentRevisions(ctx, parent, storage.PageOptions{
+		Size:  req.GetPageSize(),
+		Token: req.GetPageToken(),
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	response := &rpc.ListApiDeploymentRevisionsResponse{
+		ApiDeployments: make([]*rpc.ApiDeployment, len(listing.Deployments)),
+		NextPageToken:  listing.Token,
+	}
+
+	tags, err := db.GetDeploymentTags(ctx, parent)
+	if err != nil {
+		return nil, err
+	}
+
+	tagsByRev := deploymentTagsByRevision(tags)
+	for i, deployment := range listing.Deployments {
+		response.ApiDeployments[i], err = deployment.BasicMessage(deployment.RevisionName(), tagsByRev[deployment.RevisionName()])
+		if err != nil {
+			return nil, status.Error(codes.Internal, err.Error())
+		}
+	}
+
+	return response, nil
+}
+
+// DeleteApiDeploymentRevision handles the corresponding API request.
+func (s *RegistryServer) DeleteApiDeploymentRevision(ctx context.Context, req *rpc.DeleteApiDeploymentRevisionRequest) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	name, err := names.ParseDeploymentRevision(req.GetName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	revision, err := db.GetDeploymentRevision(ctx, name)
+	if err != nil {
+		return nil, err
+	}
+
+	// Parse the retrieved deployment revision name, which has a non-tag revision ID.
+	// This is necessary to ensure the actual revision is deleted.
+	name, err = names.ParseDeploymentRevision(revision.RevisionName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	if err := db.DeleteDeploymentRevision(ctx, name); err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	s.notify(ctx, rpc.Notification_DELETED, name.String())
+
+	// return the latest revision of the current deployment
+	deployment, err := s.getApiDeployment(ctx, name.Deployment())
+	if err != nil {
+		// This will fail if we just deleted the only revision of this deployment.
+		// TODO: prevent this.
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+	return deployment, nil
+}
+
+// TagApiDeploymentRevision handles the corresponding API request.
+func (s *RegistryServer) TagApiDeploymentRevision(ctx context.Context, req *rpc.TagApiDeploymentRevisionRequest) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	if req.GetTag() == "" {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid tag %q, must not be empty", req.GetTag())
+	} else if len(req.GetTag()) > 40 {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid tag %q, must be 40 characters or less", req.GetTag())
+	}
+
+	// Parse the requested deployment revision name, which may include a tag name.
+	name, err := names.ParseDeploymentRevision(req.GetName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	revision, err := db.GetDeploymentRevision(ctx, name)
+	if err != nil {
+		return nil, err
+	}
+
+	// Parse the retrieved deployment revision name, which has a non-tag revision ID.
+	// This is necessary to ensure the new tag is associated with a revision ID, not another tag.
+	name, err = names.ParseDeploymentRevision(revision.RevisionName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	tag := models.NewDeploymentRevisionTag(name, req.GetTag())
+	if err := db.SaveDeploymentRevisionTag(ctx, tag); err != nil {
+		return nil, err
+	}
+
+	tags, err := deploymentRevisionTags(ctx, db, name)
+	if err != nil {
+		return nil, err
+	}
+
+	message, err := revision.BasicMessage(tag.String(), tags)
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	s.notify(ctx, rpc.Notification_UPDATED, name.String())
+	return message, nil
+}
+
+// RollbackApiDeployment handles the corresponding API request.
+func (s *RegistryServer) RollbackApiDeployment(ctx context.Context, req *rpc.RollbackApiDeploymentRequest) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	if req.GetRevisionId() == "" {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid revision ID %q, must not be empty", req.GetRevisionId())
+	}
+
+	parent, err := names.ParseDeployment(req.GetName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	// Get the target deployment revision to use as a base for the new rollback revision.
+	name := parent.Revision(req.GetRevisionId())
+	target, err := db.GetDeploymentRevision(ctx, name)
+	if err != nil {
+		return nil, err
+	}
+
+	// Save a new rollback revision based on the target revision.
+	rollback := target.NewRevision()
+	if err := db.SaveDeploymentRevision(ctx, rollback); err != nil {
+		return nil, err
+	}
+
+	message, err := rollback.BasicMessage(rollback.RevisionName(), []string{})
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	s.notify(ctx, rpc.Notification_CREATED, rollback.RevisionName())
+	return message, nil
+}
diff --git a/server/registry/actions_deployments.go b/server/registry/actions_deployments.go
new file mode 100644
index 0000000..42d687a
--- /dev/null
+++ b/server/registry/actions_deployments.go
@@ -0,0 +1,302 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package registry
+
+import (
+	"context"
+
+	"github.com/apigee/registry/rpc"
+	"github.com/apigee/registry/server/registry/internal/storage"
+	"github.com/apigee/registry/server/registry/internal/storage/models"
+	"github.com/apigee/registry/server/registry/names"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+	"google.golang.org/protobuf/types/known/emptypb"
+)
+
+// CreateApiDeployment handles the corresponding API request.
+func (s *RegistryServer) CreateApiDeployment(ctx context.Context, req *rpc.CreateApiDeploymentRequest) (*rpc.ApiDeployment, error) {
+	parent, err := names.ParseApi(req.GetParent())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	if req.GetApiDeployment() == nil {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid api_deployment %+v: body must be provided", req.GetApiDeployment())
+	}
+
+	return s.createDeployment(ctx, parent.Deployment(req.GetApiDeploymentId()), req.GetApiDeployment())
+}
+
+func (s *RegistryServer) createDeployment(ctx context.Context, name names.Deployment, body *rpc.ApiDeployment) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	if _, err := db.GetDeployment(ctx, name); err == nil {
+		return nil, status.Errorf(codes.AlreadyExists, "API deployment %q already exists", name)
+	} else if !isNotFound(err) {
+		return nil, err
+	}
+
+	if err := name.Validate(); err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	// Creation should only succeed when the parent exists.
+	if _, err := db.GetApi(ctx, name.Api()); err != nil {
+		return nil, err
+	}
+
+	deployment, err := models.NewDeployment(name, body)
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	if err := db.SaveDeploymentRevision(ctx, deployment); err != nil {
+		return nil, err
+	}
+
+	message, err := deployment.BasicMessage(name.String(), []string{})
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	s.notify(ctx, rpc.Notification_CREATED, deployment.RevisionName())
+	return message, nil
+}
+
+// DeleteApiDeployment handles the corresponding API request.
+func (s *RegistryServer) DeleteApiDeployment(ctx context.Context, req *rpc.DeleteApiDeploymentRequest) (*emptypb.Empty, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	name, err := names.ParseDeployment(req.GetName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	// Deletion should only succeed on API deployments that currently exist.
+	if _, err := db.GetDeployment(ctx, name); err != nil {
+		return nil, err
+	}
+
+	if err := db.DeleteDeployment(ctx, name); err != nil {
+		return nil, err
+	}
+
+	s.notify(ctx, rpc.Notification_DELETED, name.String())
+	return &emptypb.Empty{}, nil
+}
+
+// GetApiDeployment handles the corresponding API request.
+func (s *RegistryServer) GetApiDeployment(ctx context.Context, req *rpc.GetApiDeploymentRequest) (*rpc.ApiDeployment, error) {
+	if name, err := names.ParseDeployment(req.GetName()); err == nil {
+		return s.getApiDeployment(ctx, name)
+	} else if name, err := names.ParseDeploymentRevision(req.GetName()); err == nil {
+		return s.getApiDeploymentRevision(ctx, name)
+	}
+
+	return nil, status.Errorf(codes.InvalidArgument, "invalid resource name %q, must be an API deployment or revision", req.GetName())
+}
+
+func (s *RegistryServer) getApiDeployment(ctx context.Context, name names.Deployment) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	deployment, err := db.GetDeployment(ctx, name)
+	if err != nil {
+		return nil, err
+	}
+
+	tags, err := deploymentRevisionTags(ctx, db, name.Revision(deployment.RevisionID))
+	if err != nil {
+		return nil, err
+	}
+
+	message, err := deployment.BasicMessage(name.String(), tags)
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	return message, nil
+}
+
+func (s *RegistryServer) getApiDeploymentRevision(ctx context.Context, name names.DeploymentRevision) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	revision, err := db.GetDeploymentRevision(ctx, name)
+	if err != nil {
+		return nil, err
+	}
+
+	tags, err := deploymentRevisionTags(ctx, db, name)
+	if err != nil {
+		return nil, err
+	}
+
+	message, err := revision.BasicMessage(name.String(), tags)
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	return message, nil
+}
+
+// ListApiDeployments handles the corresponding API request.
+func (s *RegistryServer) ListApiDeployments(ctx context.Context, req *rpc.ListApiDeploymentsRequest) (*rpc.ListApiDeploymentsResponse, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	if req.GetPageSize() < 0 {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid page_size %d: must not be negative", req.GetPageSize())
+	} else if req.GetPageSize() > 1000 {
+		req.PageSize = 1000
+	} else if req.GetPageSize() == 0 {
+		req.PageSize = 50
+	}
+
+	parent, err := names.ParseApi(req.GetParent())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	listing, err := db.ListDeployments(ctx, parent, storage.PageOptions{
+		Size:   req.GetPageSize(),
+		Filter: req.GetFilter(),
+		Token:  req.GetPageToken(),
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	response := &rpc.ListApiDeploymentsResponse{
+		ApiDeployments: make([]*rpc.ApiDeployment, len(listing.Deployments)),
+		NextPageToken:  listing.Token,
+	}
+
+	tags, err := db.GetDeploymentTags(ctx, parent.Deployment("-"))
+	if err != nil {
+		return nil, err
+	}
+
+	tagsByRev := deploymentTagsByRevision(tags)
+	for i, deployment := range listing.Deployments {
+		response.ApiDeployments[i], err = deployment.BasicMessage(deployment.Name(), tagsByRev[deployment.RevisionName()])
+		if err != nil {
+			return nil, status.Error(codes.Internal, err.Error())
+		}
+	}
+
+	return response, nil
+}
+
+// UpdateApiDeployment handles the corresponding API request.
+func (s *RegistryServer) UpdateApiDeployment(ctx context.Context, req *rpc.UpdateApiDeploymentRequest) (*rpc.ApiDeployment, error) {
+	db, err := s.getStorageClient(ctx)
+	if err != nil {
+		return nil, status.Error(codes.Unavailable, err.Error())
+	}
+	defer db.Close()
+
+	if req.GetApiDeployment() == nil {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid api_deployment %+v: body must be provided", req.GetApiDeployment())
+	} else if err := models.ValidateMask(req.GetApiDeployment(), req.GetUpdateMask()); err != nil {
+		return nil, status.Errorf(codes.InvalidArgument, "invalid update_mask %v: %s", req.GetUpdateMask(), err)
+	}
+
+	name, err := names.ParseDeployment(req.ApiDeployment.GetName())
+	if err != nil {
+		return nil, status.Error(codes.InvalidArgument, err.Error())
+	}
+
+	deployment, err := db.GetDeployment(ctx, name)
+	if req.GetAllowMissing() && isNotFound(err) {
+		return s.createDeployment(ctx, name, req.GetApiDeployment())
+	} else if err != nil {
+		return nil, err
+	}
+
+	// Apply the update to the deployment - possibly changing the revision ID.
+	maskExpansion := models.ExpandMask(req.GetApiDeployment(), req.GetUpdateMask())
+	if err := deployment.Update(req.GetApiDeployment(), maskExpansion); err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	// Save the updated/current deployment. This creates a new revision or updates the previous one.
+	if err := db.SaveDeploymentRevision(ctx, deployment); err != nil {
+		return nil, err
+	}
+
+	tags, err := deploymentRevisionTags(ctx, db, name.Revision(deployment.RevisionID))
+	if err != nil {
+		return nil, err
+	}
+
+	message, err := deployment.BasicMessage(name.String(), tags)
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	s.notify(ctx, rpc.Notification_UPDATED, deployment.RevisionName())
+	return message, nil
+}
+
+func deploymentRevisionTags(ctx context.Context, db *storage.Client, name names.DeploymentRevision) ([]string, error) {
+	allTags, err := db.GetDeploymentTags(ctx, name.Deployment())
+	if err != nil {
+		return nil, err
+	}
+
+	tags := make([]string, 0)
+	for _, tag := range allTags {
+		if tag.RevisionID == name.RevisionID {
+			tags = append(tags, tag.Tag)
+		}
+	}
+
+	return tags, nil
+}
+
+func deploymentTagsByRevision(tags []*models.DeploymentRevisionTag) map[string][]string {
+	revTags := make(map[string][]string, len(tags))
+	for _, tag := range tags {
+		rev := names.DeploymentRevision{
+			ProjectID:    tag.ProjectID,
+			ApiID:        tag.ApiID,
+			DeploymentID: tag.DeploymentID,
+			RevisionID:   tag.RevisionID,
+		}.String()
+
+		revTags[rev] = append(revTags[rev], tag.Tag)
+	}
+
+	return revTags
+}
diff --git a/server/registry/actions_spec_revisions.go b/server/registry/actions_spec_revisions.go
index d044c48..1eeadea 100644
--- a/server/registry/actions_spec_revisions.go
+++ b/server/registry/actions_spec_revisions.go
@@ -64,7 +64,7 @@ func (s *RegistryServer) ListApiSpecRevisions(ctx context.Context, req *rpc.List
 		return nil, err
 	}
 
-	tagsByRev := tagsByRevision(tags)
+	tagsByRev := specTagsByRevision(tags)
 	for i, spec := range listing.Specs {
 		response.ApiSpecs[i], err = spec.BasicMessage(spec.RevisionName(), tagsByRev[spec.RevisionName()])
 		if err != nil {
diff --git a/server/registry/actions_specs.go b/server/registry/actions_specs.go
index 609fb47..10fcd78 100644
--- a/server/registry/actions_specs.go
+++ b/server/registry/actions_specs.go
@@ -258,7 +258,7 @@ func (s *RegistryServer) ListApiSpecs(ctx context.Context, req *rpc.ListApiSpecs
 		return nil, err
 	}
 
-	tagsByRev := tagsByRevision(tags)
+	tagsByRev := specTagsByRevision(tags)
 	for i, spec := range listing.Specs {
 		response.ApiSpecs[i], err = spec.BasicMessage(spec.Name(), tagsByRev[spec.RevisionName()])
 		if err != nil {
@@ -343,7 +343,7 @@ func revisionTags(ctx context.Context, db *storage.Client, name names.SpecRevisi
 	return tags, nil
 }
 
-func tagsByRevision(tags []*models.SpecRevisionTag) map[string][]string {
+func specTagsByRevision(tags []*models.SpecRevisionTag) map[string][]string {
 	revTags := make(map[string][]string, len(tags))
 	for _, tag := range tags {
 		rev := names.SpecRevision{
diff --git a/server/registry/internal/storage/deployment_revisions.go b/server/registry/internal/storage/deployment_revisions.go
new file mode 100644
index 0000000..ae14633
--- /dev/null
+++ b/server/registry/internal/storage/deployment_revisions.go
@@ -0,0 +1,141 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the revisionific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+	"context"
+
+	"github.com/apigee/registry/server/registry/internal/storage/gorm"
+	"github.com/apigee/registry/server/registry/internal/storage/models"
+	"github.com/apigee/registry/server/registry/names"
+	"google.golang.org/api/iterator"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+func (d *Client) ListDeploymentRevisions(ctx context.Context, parent names.Deployment, opts PageOptions) (DeploymentList, error) {
+	q := d.NewQuery(gorm.DeploymentEntityName)
+	q = q.Require("ProjectID", parent.ProjectID)
+	q = q.Require("ApiID", parent.ApiID)
+	q = q.Require("DeploymentID", parent.DeploymentID)
+	q = q.Descending("RevisionCreateTime")
+
+	token, err := decodeToken(opts.Token)
+	if err != nil {
+		return DeploymentList{}, status.Errorf(codes.InvalidArgument, "invalid page token %q: %s", opts.Token, err.Error())
+	}
+
+	if err := token.ValidateFilter(opts.Filter); err != nil {
+		return DeploymentList{}, status.Errorf(codes.InvalidArgument, "invalid filter %q: %s", opts.Filter, err)
+	}
+
+	q = q.ApplyOffset(token.Offset)
+
+	it := d.Run(ctx, q)
+	response := DeploymentList{
+		Deployments: make([]models.Deployment, 0, opts.Size),
+	}
+
+	revision := new(models.Deployment)
+	for _, err = it.Next(revision); err == nil; _, err = it.Next(revision) {
+		token.Offset++
+
+		response.Deployments = append(response.Deployments, *revision)
+		if len(response.Deployments) == int(opts.Size) {
+			break
+		}
+	}
+	if err != nil && err != iterator.Done {
+		return response, status.Error(codes.Internal, err.Error())
+	}
+
+	if err == nil {
+		response.Token, err = encodeToken(token)
+		if err != nil {
+			return response, status.Error(codes.Internal, err.Error())
+		}
+	}
+
+	return response, nil
+}
+
+func (d *Client) SaveDeploymentRevision(ctx context.Context, revision *models.Deployment) error {
+	k := d.NewKey(gorm.DeploymentEntityName, revision.RevisionName())
+	if _, err := d.Put(ctx, k, revision); err != nil {
+		return status.Error(codes.Internal, err.Error())
+	}
+
+	return nil
+}
+
+func (d *Client) GetDeploymentRevision(ctx context.Context, name names.DeploymentRevision) (*models.Deployment, error) {
+	name, err := d.unwrapDeploymentRevisionTag(ctx, name)
+	if err != nil {
+		return nil, err
+	}
+
+	deployment := new(models.Deployment)
+	k := d.NewKey(gorm.DeploymentEntityName, name.String())
+	if err := d.Get(ctx, k, deployment); d.IsNotFound(err) {
+		return nil, status.Errorf(codes.NotFound, "deployment revision %q not found", name)
+	} else if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	return deployment, nil
+}
+
+func (d *Client) DeleteDeploymentRevision(ctx context.Context, name names.DeploymentRevision) error {
+	name, err := d.unwrapDeploymentRevisionTag(ctx, name)
+	if err != nil {
+		return err
+	}
+
+	for _, entityName := range []string{
+		gorm.DeploymentEntityName,
+		gorm.DeploymentRevisionTagEntityName,
+	} {
+		q := d.NewQuery(entityName)
+		q = q.Require("ProjectID", name.ProjectID)
+		q = q.Require("ApiID", name.ApiID)
+		q = q.Require("DeploymentID", name.DeploymentID)
+		q = q.Require("RevisionID", name.RevisionID)
+		if err := d.Delete(ctx, q); err != nil {
+			return status.Error(codes.Internal, err.Error())
+		}
+	}
+
+	return nil
+}
+
+func (d *Client) SaveDeploymentRevisionTag(ctx context.Context, tag *models.DeploymentRevisionTag) error {
+	k := d.NewKey(gorm.DeploymentRevisionTagEntityName, tag.String())
+	if _, err := d.Put(ctx, k, tag); err != nil {
+		return status.Error(codes.Internal, err.Error())
+	}
+
+	return nil
+}
+
+func (d *Client) unwrapDeploymentRevisionTag(ctx context.Context, name names.DeploymentRevision) (names.DeploymentRevision, error) {
+	tag := new(models.DeploymentRevisionTag)
+	if err := d.Get(ctx, d.NewKey(gorm.DeploymentRevisionTagEntityName, name.String()), tag); d.IsNotFound(err) {
+		return name, nil
+	} else if err != nil {
+		return names.DeploymentRevision{}, status.Error(codes.Internal, err.Error())
+	}
+
+	return name.Deployment().Revision(tag.RevisionID), nil
+}
diff --git a/server/registry/internal/storage/deployments.go b/server/registry/internal/storage/deployments.go
new file mode 100644
index 0000000..562766e
--- /dev/null
+++ b/server/registry/internal/storage/deployments.go
@@ -0,0 +1,203 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+	"context"
+
+	"github.com/apigee/registry/server/registry/internal/storage/filtering"
+	"github.com/apigee/registry/server/registry/internal/storage/gorm"
+	"github.com/apigee/registry/server/registry/internal/storage/models"
+	"github.com/apigee/registry/server/registry/names"
+	"google.golang.org/api/iterator"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// DeploymentList contains a page of deployment resources.
+type DeploymentList struct {
+	Deployments []models.Deployment
+	Token       string
+}
+
+var deploymentFields = []filtering.Field{
+	{Name: "name", Type: filtering.String},
+	{Name: "project_id", Type: filtering.String},
+	{Name: "api_id", Type: filtering.String},
+	{Name: "deployment_id", Type: filtering.String},
+	{Name: "display_name", Type: filtering.String},
+	{Name: "description", Type: filtering.String},
+	{Name: "create_time", Type: filtering.Timestamp},
+	{Name: "revision_create_time", Type: filtering.Timestamp},
+	{Name: "revision_update_time", Type: filtering.Timestamp},
+	{Name: "api_spec_revision", Type: filtering.String},
+	{Name: "endpoint_uri", Type: filtering.String},
+	{Name: "external_channel_uri", Type: filtering.String},
+	{Name: "intended_audience", Type: filtering.String},
+	{Name: "access_guidance", Type: filtering.String},
+	{Name: "labels", Type: filtering.StringMap},
+}
+
+func (d *Client) ListDeployments(ctx context.Context, parent names.Api, opts PageOptions) (DeploymentList, error) {
+	token, err := decodeToken(opts.Token)
+	if err != nil {
+		return DeploymentList{}, status.Errorf(codes.InvalidArgument, "invalid page token %q: %s", opts.Token, err.Error())
+	}
+
+	if err := token.ValidateFilter(opts.Filter); err != nil {
+		return DeploymentList{}, status.Errorf(codes.InvalidArgument, "invalid filter %q: %s", opts.Filter, err)
+	} else {
+		token.Filter = opts.Filter
+	}
+
+	if parent.ProjectID != "-" && parent.ApiID != "-" {
+		if _, err := d.GetApi(ctx, parent); err != nil {
+			return DeploymentList{}, err
+		}
+	} else if parent.ProjectID != "-" && parent.ApiID == "-" {
+		if _, err := d.GetProject(ctx, parent.Project()); err != nil {
+			return DeploymentList{}, err
+		}
+	}
+
+	filter, err := filtering.NewFilter(opts.Filter, deploymentFields)
+	if err != nil {
+		return DeploymentList{}, err
+	}
+
+	it := d.GetRecentDeploymentRevisions(ctx, token.Offset, parent.ProjectID, parent.ApiID)
+	response := DeploymentList{
+		Deployments: make([]models.Deployment, 0, opts.Size),
+	}
+
+	deployment := new(models.Deployment)
+	for _, err = it.Next(deployment); err == nil; _, err = it.Next(deployment) {
+		deploymentMap, err := deploymentMap(*deployment)
+		if err != nil {
+			return response, status.Error(codes.Internal, err.Error())
+		}
+
+		match, err := filter.Matches(deploymentMap)
+		if err != nil {
+			return response, err
+		} else if !match {
+			token.Offset++
+			continue
+		} else if len(response.Deployments) == int(opts.Size) {
+			break
+		}
+
+		response.Deployments = append(response.Deployments, *deployment)
+		token.Offset++
+	}
+	if err != nil && err != iterator.Done {
+		return response, status.Error(codes.Internal, err.Error())
+	}
+
+	if err == nil {
+		response.Token, err = encodeToken(token)
+		if err != nil {
+			return response, status.Error(codes.Internal, err.Error())
+		}
+	}
+
+	return response, nil
+}
+
+func deploymentMap(deployment models.Deployment) (map[string]interface{}, error) {
+	labels, err := deployment.LabelsMap()
+	if err != nil {
+		return nil, err
+	}
+
+	return map[string]interface{}{
+		"name":                 deployment.Name(),
+		"project_id":           deployment.ProjectID,
+		"api_id":               deployment.ApiID,
+		"deployment_id":        deployment.DeploymentID,
+		"revision_id":          deployment.RevisionID,
+		"display_name":         deployment.DisplayName,
+		"description":          deployment.Description,
+		"create_time":          deployment.CreateTime,
+		"revision_create_time": deployment.RevisionCreateTime,
+		"revision_update_time": deployment.RevisionUpdateTime,
+		"api_spec_revision":    deployment.ApiSpecRevision,
+		"endpoint_uri":         deployment.EndpointURI,
+		"external_channel_uri": deployment.ExternalChannelURI,
+		"intended_audience":    deployment.IntendedAudience,
+		"access_guidance":      deployment.AccessGuidance,
+		"labels":               labels,
+	}, nil
+}
+
+func (d *Client) GetDeployment(ctx context.Context, name names.Deployment) (*models.Deployment, error) {
+	normal := name.Normal()
+	q := d.NewQuery(gorm.DeploymentEntityName)
+	q = q.Require("ProjectID", normal.ProjectID)
+	q = q.Require("ApiID", normal.ApiID)
+	q = q.Require("DeploymentID", normal.DeploymentID)
+	q = q.Descending("RevisionCreateTime")
+
+	it := d.Run(ctx, q)
+	deployment := &models.Deployment{}
+	if _, err := it.Next(deployment); err != nil {
+		return nil, status.Error(codes.NotFound, err.Error())
+	}
+
+	return deployment, nil
+}
+
+func (d *Client) DeleteDeployment(ctx context.Context, name names.Deployment) error {
+	for _, entityName := range []string{
+		gorm.DeploymentEntityName,
+		gorm.DeploymentRevisionTagEntityName,
+		gorm.ArtifactEntityName,
+	} {
+		q := d.NewQuery(entityName)
+		q = q.Require("ProjectID", name.ProjectID)
+		q = q.Require("ApiID", name.ApiID)
+		q = q.Require("DeploymentID", name.DeploymentID)
+		if err := d.Delete(ctx, q); err != nil {
+			return status.Error(codes.Internal, err.Error())
+		}
+	}
+
+	return nil
+}
+
+func (d *Client) GetDeploymentTags(ctx context.Context, name names.Deployment) ([]*models.DeploymentRevisionTag, error) {
+	q := d.NewQuery(gorm.DeploymentRevisionTagEntityName)
+	q = q.Require("ProjectID", name.ProjectID)
+	q = q.Require("ApiID", name.ApiID)
+	if name.DeploymentID != "-" {
+		q = q.Require("DeploymentID", name.DeploymentID)
+	}
+
+	var (
+		tags = make([]*models.DeploymentRevisionTag, 0)
+		tag  = new(models.DeploymentRevisionTag)
+		it   = d.Run(ctx, q)
+		err  error
+	)
+
+	for _, err = it.Next(tag); err == nil; _, err = it.Next(tag) {
+		tags = append(tags, tag)
+	}
+	if err != nil && err != iterator.Done {
+		return nil, status.Error(codes.Internal, err.Error())
+	}
+
+	return tags, nil
+}
diff --git a/server/registry/internal/storage/gorm/client.go b/server/registry/internal/storage/gorm/client.go
index 4e15fb0..c7330f5 100644
--- a/server/registry/internal/storage/gorm/client.go
+++ b/server/registry/internal/storage/gorm/client.go
@@ -122,9 +122,11 @@ func (c *Client) ensure() {
 	c.ensureTable(&models.Api{})
 	c.ensureTable(&models.Version{})
 	c.ensureTable(&models.Spec{})
-	c.ensureTable(&models.Blob{})
-	c.ensureTable(&models.Artifact{})
 	c.ensureTable(&models.SpecRevisionTag{})
+	c.ensureTable(&models.Deployment{})
+	c.ensureTable(&models.DeploymentRevisionTag{})
+	c.ensureTable(&models.Artifact{})
+	c.ensureTable(&models.Blob{})
 }
 
 // IsNotFound returns true if an error is due to an entity not being found.
@@ -154,10 +156,14 @@ func (c *Client) Put(ctx context.Context, k *Key, v interface{}) (*Key, error) {
 		r.Key = k.Name
 	case *models.SpecRevisionTag:
 		r.Key = k.Name
-	case *models.Blob:
+	case *models.Deployment:
+		r.Key = k.Name
+	case *models.DeploymentRevisionTag:
 		r.Key = k.Name
 	case *models.Artifact:
 		r.Key = k.Name
+	case *models.Blob:
+		r.Key = k.Name
 	}
 	_ = c.db.Transaction(func(tx *gorm.DB) error {
 		// Update all fields from model: https://gorm.io/docs/update.html#Update-Selected-Fields
@@ -185,12 +191,16 @@ func (c *Client) Delete(ctx context.Context, q *Query) error {
 		return op.Delete(models.Version{}).Error
 	case "Spec":
 		return op.Delete(models.Spec{}).Error
-	case "Blob":
-		return op.Delete(models.Blob{}).Error
-	case "Artifact":
-		return op.Delete(models.Artifact{}).Error
 	case "SpecRevisionTag":
 		return op.Delete(models.SpecRevisionTag{}).Error
+	case "Deployment":
+		return op.Delete(models.Deployment{}).Error
+	case "DeploymentRevisionTag":
+		return op.Delete(models.DeploymentRevisionTag{}).Error
+	case "Artifact":
+		return op.Delete(models.Artifact{}).Error
+	case "Blob":
+		return op.Delete(models.Blob{}).Error
 	}
 	return nil
 }
@@ -233,6 +243,18 @@ func (c *Client) Run(ctx context.Context, q *Query) *Iterator {
 		var v []models.Spec
 		_ = op.Find(&v).Error
 		return &Iterator{Client: c, Values: v, Index: 0}
+	case "SpecRevisionTag":
+		var v []models.SpecRevisionTag
+		_ = op.Find(&v).Error
+		return &Iterator{Client: c, Values: v, Index: 0}
+	case "Deployment":
+		var v []models.Deployment
+		_ = op.Find(&v).Error
+		return &Iterator{Client: c, Values: v, Index: 0}
+	case "DeploymentRevisionTag":
+		var v []models.DeploymentRevisionTag
+		_ = op.Find(&v).Error
+		return &Iterator{Client: c, Values: v, Index: 0}
 	case "Blob":
 		var v []models.Blob
 		_ = op.Find(&v).Error
@@ -241,10 +263,6 @@ func (c *Client) Run(ctx context.Context, q *Query) *Iterator {
 		var v []models.Artifact
 		_ = op.Find(&v).Error
 		return &Iterator{Client: c, Values: v, Index: 0}
-	case "SpecRevisionTag":
-		var v []models.SpecRevisionTag
-		_ = op.Find(&v).Error
-		return &Iterator{Client: c, Values: v, Index: 0}
 	default:
 		return nil
 	}
@@ -284,3 +302,35 @@ func (c *Client) GetRecentSpecRevisions(ctx context.Context, offset int32, proje
 	_ = op.Scan(&v).Error
 	return &Iterator{Client: c, Values: v, Index: 0}
 }
+
+func (c *Client) GetRecentDeploymentRevisions(ctx context.Context, offset int32, projectID, apiID string) *Iterator {
+	lock()
+	defer unlock()
+
+	// Select all columns from `deployments` table specifically.
+	// We do not want to select duplicates from the joined subquery result.
+	op := c.db.Select("deployments.*").
+		Table("deployments").
+		// Join missing columns that couldn't be selected in the subquery.
+		Joins("JOIN (?) AS grp ON deployments.project_id = grp.project_id AND deployments.api_id = grp.api_id AND deployments.deployment_id = grp.deployment_id AND deployments.revision_create_time = grp.recent_create_time",
+			// Select deployment names and only their most recent revision_create_time
+			// This query cannot select all the columns we want.
+			// See: https://stackoverflow.com/questions/7745609/sql-select-only-rows-with-max-value-on-a-column
+			c.db.Select("project_id, api_id, deployment_id, MAX(revision_create_time) AS recent_create_time").
+				Table("deployments").
+				Group("project_id, api_id, deployment_id")).
+		Order("key").
+		Offset(int(offset)).
+		Limit(100000)
+
+	if projectID != "-" {
+		op = op.Where("deployments.project_id = ?", projectID)
+	}
+	if apiID != "-" {
+		op = op.Where("deployments.api_id = ?", apiID)
+	}
+
+	var v []models.Deployment
+	_ = op.Scan(&v).Error
+	return &Iterator{Client: c, Values: v, Index: 0}
+}
diff --git a/server/registry/internal/storage/gorm/entities.go b/server/registry/internal/storage/gorm/entities.go
index 515be31..2ede51e 100644
--- a/server/registry/internal/storage/gorm/entities.go
+++ b/server/registry/internal/storage/gorm/entities.go
@@ -25,6 +25,10 @@ const (
 	SpecEntityName = "Spec"
 	// SpecRevisionTagEntityName is the storage entity name for API spec revision tag resources.
 	SpecRevisionTagEntityName = "SpecRevisionTag"
+	// DeploymentEntityName is the storage entity name for API deployment resources.
+	DeploymentEntityName = "Deployment"
+	// DeploymentRevisionTagEntityName is the storage entity name for API deployment revision tag resources.
+	DeploymentRevisionTagEntityName = "DeploymentRevisionTag"
 	// ArtifactEntityName is the storage entity name for artifact resources.
 	ArtifactEntityName = "Artifact"
 	// BlobEntityName is the storage entity name for blob resources.
diff --git a/server/registry/internal/storage/gorm/iterator.go b/server/registry/internal/storage/gorm/iterator.go
index 3c7de22..34ef530 100644
--- a/server/registry/internal/storage/gorm/iterator.go
+++ b/server/registry/internal/storage/gorm/iterator.go
@@ -75,6 +75,15 @@ func (it *Iterator) Next(v interface{}) (*Key, error) {
 			return it.Client.NewKey("Spec", x.Key), nil
 		}
 		return nil, iterator.Done
+	case *models.Deployment:
+		values := it.Values.([]models.Deployment)
+		if it.Index < len(values) {
+			*x = values[it.Index]
+			it.Cursor = x.Key
+			it.Index++
+			return it.Client.NewKey("Deployment", x.Key), nil
+		}
+		return nil, iterator.Done
 	case *models.Blob:
 		values := it.Values.([]models.Blob)
 		if it.Index < len(values) {
@@ -102,6 +111,15 @@ func (it *Iterator) Next(v interface{}) (*Key, error) {
 			return it.Client.NewKey("SpecRevisionTag", x.Key), nil
 		}
 		return nil, iterator.Done
+	case *models.DeploymentRevisionTag:
+		values := it.Values.([]models.DeploymentRevisionTag)
+		if it.Index < len(values) {
+			*x = values[it.Index]
+			it.Cursor = x.Key
+			it.Index++
+			return it.Client.NewKey("DeploymentRevisionTag", x.Key), nil
+		}
+		return nil, iterator.Done
 	default:
 		return nil, fmt.Errorf("unsupported iterator type: %t", v)
 	}
diff --git a/server/registry/internal/storage/gorm/query.go b/server/registry/internal/storage/gorm/query.go
index e2db15a..ce4050e 100644
--- a/server/registry/internal/storage/gorm/query.go
+++ b/server/registry/internal/storage/gorm/query.go
@@ -46,6 +46,8 @@ func (q *Query) Require(name string, value interface{}) *Query {
 		name = "version_id"
 	case "SpecID":
 		name = "spec_id"
+	case "DeploymentID":
+		name = "deployment_id"
 	case "RevisionID":
 		name = "revision_id"
 	case "ArtifactID":
diff --git a/server/registry/internal/storage/models/artifact.go b/server/registry/internal/storage/models/artifact.go
index 5b4262a..fbe416c 100644
--- a/server/registry/internal/storage/models/artifact.go
+++ b/server/registry/internal/storage/models/artifact.go
@@ -28,31 +28,33 @@ import (
 
 // Artifact is the storage-side representation of an artifact.
 type Artifact struct {
-	Key         string    `gorm:"primaryKey"`
-	ProjectID   string    // Project associated with artifact (required).
-	ApiID       string    // Api associated with artifact (if appropriate).
-	VersionID   string    // Version associated with artifact (if appropriate).
-	SpecID      string    // Spec associated with artifact (if appropriate).
-	ArtifactID  string    // Artifact identifier (required).
-	CreateTime  time.Time // Creation time.
-	UpdateTime  time.Time // Time of last change.
-	MimeType    string    // MIME type of artifact
-	SizeInBytes int32     // Size of the spec.
-	Hash        string    // A hash of the spec.
+	Key          string    `gorm:"primaryKey"`
+	ProjectID    string    // Project associated with artifact (required).
+	ApiID        string    // Api associated with artifact (if appropriate).
+	VersionID    string    // Version associated with artifact (if appropriate).
+	SpecID       string    // Spec associated with artifact (if appropriate).
+	DeploymentID string    // Deployment associated with artifact (if appropriate).
+	ArtifactID   string    // Artifact identifier (required).
+	CreateTime   time.Time // Creation time.
+	UpdateTime   time.Time // Time of last change.
+	MimeType     string    // MIME type of artifact
+	SizeInBytes  int32     // Size of the spec.
+	Hash         string    // A hash of the spec.
 }
 
 // NewArtifact initializes a new resource.
 func NewArtifact(name names.Artifact, body *rpc.Artifact) (artifact *Artifact, err error) {
 	now := time.Now().Round(time.Microsecond)
 	artifact = &Artifact{
-		ProjectID:  name.ProjectID(),
-		ApiID:      name.ApiID(),
-		VersionID:  name.VersionID(),
-		SpecID:     name.SpecID(),
-		ArtifactID: name.ArtifactID(),
-		CreateTime: now,
-		UpdateTime: now,
-		MimeType:   body.GetMimeType(),
+		ProjectID:    name.ProjectID(),
+		ApiID:        name.ApiID(),
+		VersionID:    name.VersionID(),
+		SpecID:       name.SpecID(),
+		DeploymentID: name.DeploymentID(),
+		ArtifactID:   name.ArtifactID(),
+		CreateTime:   now,
+		UpdateTime:   now,
+		MimeType:     body.GetMimeType(),
 	}
 
 	if body.GetContents() != nil {
@@ -80,6 +82,9 @@ func (artifact *Artifact) Name() string {
 	case artifact.VersionID != "":
 		return fmt.Sprintf("projects/%s/locations/%s/apis/%s/versions/%s/artifacts/%s",
 			artifact.ProjectID, names.Location, artifact.ApiID, artifact.VersionID, artifact.ArtifactID)
+	case artifact.DeploymentID != "":
+		return fmt.Sprintf("projects/%s/locations/%s/apis/%s/deployments/%s/artifacts/%s",
+			artifact.ProjectID, names.Location, artifact.ApiID, artifact.DeploymentID, artifact.ArtifactID)
 	case artifact.ApiID != "":
 		return fmt.Sprintf("projects/%s/locations/%s/apis/%s/artifacts/%s",
 			artifact.ProjectID, names.Location, artifact.ApiID, artifact.ArtifactID)
diff --git a/server/registry/internal/storage/models/deployment.go b/server/registry/internal/storage/models/deployment.go
new file mode 100644
index 0000000..640d60b
--- /dev/null
+++ b/server/registry/internal/storage/models/deployment.go
@@ -0,0 +1,230 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package models
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/apigee/registry/rpc"
+	"github.com/apigee/registry/server/registry/names"
+	"google.golang.org/protobuf/types/known/fieldmaskpb"
+	"google.golang.org/protobuf/types/known/timestamppb"
+)
+
+// Deployment is the storage-side representation of a deployment.
+type Deployment struct {
+	Key                string    `gorm:"primaryKey"`
+	ProjectID          string    // Uniquely identifies a project.
+	ApiID              string    // Uniquely identifies an api within a project.
+	DeploymentID       string    // Uniquely identifies a deployment within an api.
+	RevisionID         string    // Uniquely identifies a revision of a deployment.
+	DisplayName        string    // A human-friendly name.
+	Description        string    // A detailed description.
+	CreateTime         time.Time // Creation time.
+	RevisionCreateTime time.Time // Revision creation time.
+	RevisionUpdateTime time.Time // Time of last change.
+	ApiSpecRevision    string    // The spec being served by the deployment.
+	EndpointURI        string    // The address where the deployment is serving.
+	ExternalChannelURI string    // The address of the external channel of the API.
+	IntendedAudience   string    // The intended audience of the API.
+	AccessGuidance     string    // A brief description of how to access the endpoint.
+	Labels             []byte    // Serialized labels.
+	Annotations        []byte    // Serialized annotations.
+}
+
+// NewDeployment initializes a new resource.
+func NewDeployment(name names.Deployment, body *rpc.ApiDeployment) (deployment *Deployment, err error) {
+	now := time.Now().Round(time.Microsecond)
+	deployment = &Deployment{
+		ProjectID:          name.ProjectID,
+		ApiID:              name.ApiID,
+		DeploymentID:       name.DeploymentID,
+		RevisionID:         newRevisionID(),
+		DisplayName:        body.GetDisplayName(),
+		Description:        body.GetDescription(),
+		CreateTime:         now,
+		RevisionCreateTime: now,
+		RevisionUpdateTime: now,
+		ApiSpecRevision:    body.GetApiSpecRevision(),
+		EndpointURI:        body.GetEndpointUri(),
+		ExternalChannelURI: body.GetExternalChannelUri(),
+		IntendedAudience:   body.GetIntendedAudience(),
+		AccessGuidance:     body.GetAccessGuidance(),
+	}
+
+	deployment.Labels, err = bytesForMap(body.GetLabels())
+	if err != nil {
+		return nil, err
+	}
+
+	deployment.Annotations, err = bytesForMap(body.GetAnnotations())
+	if err != nil {
+		return nil, err
+	}
+
+	return deployment, nil
+}
+
+// NewRevision returns a new revision based on the deployment.
+func (s *Deployment) NewRevision() *Deployment {
+	now := time.Now().Round(time.Microsecond)
+	return &Deployment{
+		ProjectID:          s.ProjectID,
+		ApiID:              s.ApiID,
+		DeploymentID:       s.DeploymentID,
+		RevisionID:         newRevisionID(),
+		DisplayName:        s.DisplayName,
+		Description:        s.Description,
+		CreateTime:         s.CreateTime,
+		RevisionCreateTime: now,
+		RevisionUpdateTime: now,
+		ApiSpecRevision:    s.ApiSpecRevision,
+		EndpointURI:        s.EndpointURI,
+		ExternalChannelURI: s.ExternalChannelURI,
+		IntendedAudience:   s.IntendedAudience,
+		AccessGuidance:     s.AccessGuidance,
+	}
+}
+
+// Name returns the resource name of the deployment.
+func (s *Deployment) Name() string {
+	return names.Deployment{
+		ProjectID:    s.ProjectID,
+		ApiID:        s.ApiID,
+		DeploymentID: s.DeploymentID,
+	}.String()
+}
+
+// RevisionName generates the resource name of the deployment revision.
+func (s *Deployment) RevisionName() string {
+	return fmt.Sprintf("projects/%s/locations/%s/apis/%s/deployments/%s@%s",
+		s.ProjectID, names.Location, s.ApiID, s.DeploymentID, s.RevisionID)
+}
+
+// BasicMessage returns the basic view of the deployment resource as an RPC message.
+func (s *Deployment) BasicMessage(name string, tags []string) (message *rpc.ApiDeployment, err error) {
+	message = &rpc.ApiDeployment{
+		Name:               name,
+		DisplayName:        s.DisplayName,
+		Description:        s.Description,
+		RevisionId:         s.RevisionID,
+		RevisionTags:       tags,
+		CreateTime:         timestamppb.New(s.CreateTime),
+		RevisionCreateTime: timestamppb.New(s.RevisionCreateTime),
+		RevisionUpdateTime: timestamppb.New(s.RevisionUpdateTime),
+		ApiSpecRevision:    s.ApiSpecRevision,
+		EndpointUri:        s.EndpointURI,
+		ExternalChannelUri: s.ExternalChannelURI,
+		IntendedAudience:   s.IntendedAudience,
+		AccessGuidance:     s.AccessGuidance,
+	}
+
+	message.Labels, err = mapForBytes(s.Labels)
+	if err != nil {
+		return nil, err
+	}
+
+	message.Annotations, err = mapForBytes(s.Annotations)
+	if err != nil {
+		return nil, err
+	}
+
+	return message, nil
+}
+
+// Update modifies a deployment using the contents of a message.
+func (s *Deployment) Update(message *rpc.ApiDeployment, mask *fieldmaskpb.FieldMask) error {
+	needsNewRevision := false // we update the revision if certain fields change
+	s.RevisionUpdateTime = time.Now().Round(time.Microsecond)
+	for _, field := range mask.Paths {
+		switch field {
+		case "display_name":
+			s.DisplayName = message.GetDisplayName()
+		case "description":
+			s.Description = message.GetDescription()
+		case "api_spec_revision":
+			if s.ApiSpecRevision != message.GetApiSpecRevision() {
+				needsNewRevision = true
+			}
+			s.ApiSpecRevision = message.GetApiSpecRevision()
+		case "endpoint_uri":
+			if s.EndpointURI != message.GetEndpointUri() {
+				needsNewRevision = true
+			}
+			s.EndpointURI = message.GetEndpointUri()
+		case "external_channel_uri":
+			s.ExternalChannelURI = message.GetExternalChannelUri()
+		case "intended_audience":
+			s.IntendedAudience = message.GetIntendedAudience()
+		case "access_guidance":
+			s.AccessGuidance = message.GetAccessGuidance()
+		case "labels":
+			var err error
+			if s.Labels, err = bytesForMap(message.GetLabels()); err != nil {
+				return err
+			}
+		case "annotations":
+			var err error
+			if s.Annotations, err = bytesForMap(message.GetAnnotations()); err != nil {
+				return err
+			}
+		}
+		if needsNewRevision {
+			s.RevisionID = newRevisionID()
+			now := time.Now().Round(time.Microsecond)
+			s.RevisionCreateTime = now
+			s.RevisionUpdateTime = now
+		}
+	}
+
+	return nil
+}
+
+// LabelsMap returns a map representation of stored labels.
+func (s *Deployment) LabelsMap() (map[string]string, error) {
+	return mapForBytes(s.Labels)
+}
+
+// DeploymentRevisionTag is the storage-side representation of a deployment revision tag.
+type DeploymentRevisionTag struct {
+	Key          string    `gorm:"primaryKey"`
+	ProjectID    string    // Uniquely identifies a project.
+	ApiID        string    // Uniquely identifies an api within a project.
+	DeploymentID string    // Uniquely identifies a deployment within an api.
+	RevisionID   string    // Uniquely identifies a revision of a deployment.
+	Tag          string    // The tag to use for the revision.
+	CreateTime   time.Time // Creation time.
+	UpdateTime   time.Time // Time of last change.
+}
+
+// NewDeploymentRevisionTag initializes a new revision tag from a given revision name and tag string.
+func NewDeploymentRevisionTag(name names.DeploymentRevision, tag string) *DeploymentRevisionTag {
+	now := time.Now().Round(time.Microsecond)
+	return &DeploymentRevisionTag{
+		ProjectID:    name.ProjectID,
+		ApiID:        name.ApiID,
+		DeploymentID: name.DeploymentID,
+		RevisionID:   name.RevisionID,
+		Tag:          tag,
+		CreateTime:   now,
+		UpdateTime:   now,
+	}
+}
+
+func (t *DeploymentRevisionTag) String() string {
+	return fmt.Sprintf("projects/%s/locations/%s/apis/%s/deployments/%s@%s",
+		t.ProjectID, names.Location, t.ApiID, t.DeploymentID, t.Tag)
+}
diff --git a/server/registry/internal/storage/spec_revisions.go b/server/registry/internal/storage/spec_revisions.go
index 2dcc606..c25a19a 100644
--- a/server/registry/internal/storage/spec_revisions.go
+++ b/server/registry/internal/storage/spec_revisions.go
@@ -1,6 +1,6 @@
 // Copyright 2020 Google LLC. All Rights Reserved.
 //
-// Licensed under the Apache License, Spec 2.0 (the "License");
+// Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
diff --git a/server/registry/internal/storage/specs.go b/server/registry/internal/storage/specs.go
index 10c0b92..9962874 100644
--- a/server/registry/internal/storage/specs.go
+++ b/server/registry/internal/storage/specs.go
@@ -1,6 +1,6 @@
 // Copyright 2020 Google LLC. All Rights Reserved.
 //
-// Licensed under the Apache License, Spec 2.0 (the "License");
+// Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
diff --git a/server/registry/names/deployment.go b/server/registry/names/deployment.go
index 61e3961..5f34553 100644
--- a/server/registry/names/deployment.go
+++ b/server/registry/names/deployment.go
@@ -1,4 +1,4 @@
-// Copyright 2020 Google LLC. All Rights Reserved.
+// Copyright 2021 Google LLC. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/server/registry/names/deployment_revision.go b/server/registry/names/deployment_revision.go
index 11720b8..8f3bff4 100644
--- a/server/registry/names/deployment_revision.go
+++ b/server/registry/names/deployment_revision.go
@@ -1,4 +1,4 @@
-// Copyright 2020 Google LLC. All Rights Reserved.
+// Copyright 2021 Google LLC. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.


Test patch:
diff --git a/server/registry/actions_deployment_revisions_test.go b/server/registry/actions_deployment_revisions_test.go
new file mode 100644
index 0000000..1b9392b
--- /dev/null
+++ b/server/registry/actions_deployment_revisions_test.go
@@ -0,0 +1,483 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package registry
+
+import (
+	"context"
+	"fmt"
+	"testing"
+
+	"github.com/apigee/registry/rpc"
+	"github.com/apigee/registry/server/registry/internal/test/seeder"
+	"github.com/google/go-cmp/cmp"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/testing/protocmp"
+)
+
+var (
+	// Example deployment api_spec_revision.
+	deploymentApiSpecRevision = "/projects/p/apis/a/versions/v/specs/s@12345678"
+)
+
+func TestTagApiDeploymentRevision(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	if err := seeder.SeedDeployments(ctx, server, &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/my-api/deployments/d"}); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	updateReq := &rpc.UpdateApiDeploymentRequest{
+		ApiDeployment: &rpc.ApiDeployment{
+			Name:            "projects/my-project/locations/global/apis/my-api/deployments/d",
+			ApiSpecRevision: deploymentApiSpecRevision,
+		},
+	}
+
+	revision, err := server.UpdateApiDeployment(ctx, updateReq)
+	if err != nil {
+		t.Fatalf("Setup: UpdateApiDeployment(%+v) returned error: %s", updateReq, err)
+	}
+
+	req := &rpc.TagApiDeploymentRevisionRequest{
+		Name: fmt.Sprintf("%s@%s", revision.GetName(), revision.GetRevisionId()),
+		Tag:  "my-tag",
+	}
+
+	got, err := server.TagApiDeploymentRevision(ctx, req)
+	if err != nil {
+		t.Fatalf("TagApiDeploymentRevision(%+v) returned error: %s", req, err)
+	}
+
+	opts := cmp.Options{
+		protocmp.Transform(),
+		protocmp.IgnoreFields(revision, "name", "revision_tags"),
+	}
+
+	t.Run("response", func(t *testing.T) {
+		if !cmp.Equal(revision, got, opts) {
+			t.Errorf("TagApiDeploymentRevision(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(revision, got, opts))
+		}
+
+		if want := fmt.Sprintf("%s@my-tag", revision.GetName()); want != got.GetName() {
+			t.Errorf("TagApiDeploymentRevision(%+v) returned unexpected name %q, want %q", req, got.GetName(), want)
+		}
+	})
+
+	t.Run("GetApiDeployment", func(t *testing.T) {
+		req := &rpc.GetApiDeploymentRequest{
+			Name: got.GetName(),
+		}
+
+		got, err := server.GetApiDeployment(ctx, req)
+		if err != nil {
+			t.Fatalf("GetApiDeployment(%+v) returned error: %s", req, err)
+		}
+
+		if !cmp.Equal(revision, got, opts) {
+			t.Errorf("GetApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(revision, got, opts))
+		}
+
+		if got.GetName() != req.GetName() {
+			t.Errorf("GetApiDeployment(%+v) returned unexpected name %q, want %q", req, got.GetName(), req.GetName())
+		}
+	})
+
+	t.Run("add another tag to a tagged revision", func(t *testing.T) {
+		req := &rpc.TagApiDeploymentRevisionRequest{
+			Name: got.GetName(),
+			Tag:  "my-second-tag",
+		}
+
+		got, err := server.TagApiDeploymentRevision(ctx, req)
+		if err != nil {
+			t.Fatalf("TagApiDeploymentRevision(%+v) returned error: %s", req, err)
+		}
+
+		opts := cmp.Options{
+			protocmp.Transform(),
+			protocmp.IgnoreFields(revision, "name", "revision_tags"),
+		}
+
+		if !cmp.Equal(revision, got, opts) {
+			t.Errorf("TagApiDeploymentRevision(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(revision, got, opts))
+		}
+
+		if want := fmt.Sprintf("%s@my-second-tag", revision.GetName()); want != got.GetName() {
+			t.Errorf("TagApiDeploymentRevision(%+v) returned unexpected name %q, want %q", req, got.GetName(), want)
+		}
+
+		t.Run("GetApiDeployment", func(t *testing.T) {
+			req := &rpc.GetApiDeploymentRequest{
+				Name: got.GetName(),
+			}
+
+			got, err := server.GetApiDeployment(ctx, req)
+			if err != nil {
+				t.Fatalf("GetApiDeployment(%+v) returned error: %s", req, err)
+			}
+
+			if !cmp.Equal(revision, got, opts) {
+				t.Errorf("GetApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(revision, got, opts))
+			}
+
+			if got.GetName() != req.GetName() {
+				t.Errorf("GetApiDeployment(%+v) returned unexpected name %q, want %q", req, got.GetName(), req.GetName())
+			}
+		})
+	})
+
+	t.Run("DeleteApiDeploymentRevision", func(t *testing.T) {
+		req := &rpc.DeleteApiDeploymentRevisionRequest{
+			Name: got.GetName(),
+		}
+
+		if _, err := server.DeleteApiDeploymentRevision(ctx, req); err != nil {
+			t.Fatalf("DeleteApiDeploymentRevision(%+v) returned error: %s", req, err)
+		}
+
+		t.Run("GetApiDeployment", func(t *testing.T) {
+			req := &rpc.GetApiDeploymentRequest{
+				Name: req.GetName(),
+			}
+
+			if _, err := server.GetApiDeployment(ctx, req); status.Code(err) != codes.NotFound {
+				t.Fatalf("GetApiDeployment(%+v) returned status code %q, want %q: %v", req, status.Code(err), codes.NotFound, err)
+			}
+		})
+	})
+}
+
+func TestRollbackApiDeployment(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	if err := seeder.SeedApis(ctx, server, &rpc.Api{Name: "projects/my-project/locations/global/apis/my-api"}); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	createReq := &rpc.CreateApiDeploymentRequest{
+		Parent:          "projects/my-project/locations/global/apis/my-api",
+		ApiDeploymentId: "d",
+		ApiDeployment:   &rpc.ApiDeployment{},
+	}
+
+	firstRevision, err := server.CreateApiDeployment(ctx, createReq)
+	if err != nil {
+		t.Fatalf("Setup: CreateApiDeployment(%+v) returned error: %s", createReq, err)
+	}
+
+	// Create a new revision so we can roll back from it.
+	updateReq := &rpc.UpdateApiDeploymentRequest{
+		ApiDeployment: &rpc.ApiDeployment{
+			Name:            firstRevision.GetName(),
+			ApiSpecRevision: deploymentApiSpecRevision,
+		},
+	}
+
+	secondRevision, err := server.UpdateApiDeployment(ctx, updateReq)
+	if err != nil {
+		t.Fatalf("Setup: UpdateApiDeployment(%+v) returned error: %s", updateReq, err)
+	}
+
+	if secondRevision.GetRevisionId() == firstRevision.GetRevisionId() {
+		t.Fatalf("Setup: UpdateApiDeployment(%+v) returned unexpected revision_id %q matching first revision, expected new revision ID", updateReq, secondRevision.GetRevisionId())
+	}
+
+	req := &rpc.RollbackApiDeploymentRequest{
+		Name:       secondRevision.GetName(),
+		RevisionId: firstRevision.GetRevisionId(),
+	}
+
+	rollback, err := server.RollbackApiDeployment(ctx, req)
+	if err != nil {
+		t.Fatalf("RollbackApiDeployment(%+v) returned error: %s", req, err)
+	}
+
+	want := &rpc.ApiDeployment{
+		Name:               fmt.Sprintf("%s@%s", firstRevision.GetName(), rollback.GetRevisionId()),
+		ApiSpecRevision:    firstRevision.GetApiSpecRevision(),
+		CreateTime:         firstRevision.GetCreateTime(),
+		RevisionCreateTime: firstRevision.GetRevisionCreateTime(),
+		RevisionUpdateTime: firstRevision.GetRevisionUpdateTime(),
+	}
+
+	opts := cmp.Options{
+		protocmp.Transform(),
+		protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "revision_create_time", "revision_update_time"),
+	}
+
+	if !cmp.Equal(want, rollback, opts) {
+		t.Errorf("RollbackApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(want, rollback, opts))
+	}
+
+	// Rollback should create a new revision, i.e. it should not reuse an existing revision ID.
+	if rollback.GetRevisionId() == firstRevision.GetRevisionId() {
+		t.Fatalf("RollbackApiDeployment(%+v) returned unexpected revision_id %q matching first revision, expected new revision ID", req, rollback.GetRevisionId())
+	} else if rollback.GetRevisionId() == secondRevision.GetRevisionId() {
+		t.Fatalf("RollbackApiDeployment(%+v) returned unexpected revision_id %q matching second revision, expected new revision ID", req, rollback.GetRevisionId())
+	}
+}
+
+func TestDeleteApiDeploymentRevision(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	if err := seeder.SeedDeployments(ctx, server, &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/my-api/deployments/d"}); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	t.Run("only remaining revision", func(t *testing.T) {
+		t.Skip("not yet supported")
+
+		req := &rpc.DeleteApiDeploymentRevisionRequest{
+			Name: "projects/my-project/locations/global/apis/my-api/deployments/d",
+		}
+
+		if _, err := server.DeleteApiDeploymentRevision(ctx, req); status.Code(err) != codes.FailedPrecondition {
+			t.Fatalf("DeleteApiDeploymentRevision(%+v) returned unexpected status code %q, want %q: %v", req, status.Code(err), codes.FailedPrecondition, err)
+		}
+	})
+
+	// Create a new revision so we can delete it.
+	updateReq := &rpc.UpdateApiDeploymentRequest{
+		ApiDeployment: &rpc.ApiDeployment{
+			Name:            "projects/my-project/locations/global/apis/my-api/deployments/d",
+			ApiSpecRevision: deploymentApiSpecRevision,
+		},
+	}
+
+	secondRevision, err := server.UpdateApiDeployment(ctx, updateReq)
+	if err != nil {
+		t.Fatalf("Setup: UpdateApiDeployment(%+v) returned error: %s", updateReq, err)
+	}
+
+	t.Run("one of multiple existing revisions", func(t *testing.T) {
+		req := &rpc.DeleteApiDeploymentRevisionRequest{
+			Name: fmt.Sprintf("projects/my-project/locations/global/apis/my-api/deployments/d@%s", secondRevision.GetRevisionId()),
+		}
+
+		if _, err := server.DeleteApiDeploymentRevision(ctx, req); err != nil {
+			t.Fatalf("DeleteApiDeploymentRevision(%+v) returned error: %s", req, err)
+		}
+
+		t.Run("GetApiDeployment", func(t *testing.T) {
+			req := &rpc.GetApiDeploymentRequest{
+				Name: req.GetName(),
+			}
+
+			if _, err := server.GetApiDeployment(ctx, req); status.Code(err) != codes.NotFound {
+				t.Fatalf("GetApiDeployment(%+v) returned status code %q, want %q: %v", req, status.Code(err), codes.NotFound, err)
+			}
+		})
+	})
+}
+
+func TestListApiDeploymentRevisions(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	if err := seeder.SeedApis(ctx, server, &rpc.Api{Name: "projects/my-project/locations/global/apis/my-api"}); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	createReq := &rpc.CreateApiDeploymentRequest{
+		Parent:          "projects/my-project/locations/global/apis/my-api",
+		ApiDeploymentId: "d",
+		ApiDeployment:   &rpc.ApiDeployment{},
+	}
+
+	firstRevision, err := server.CreateApiDeployment(ctx, createReq)
+	if err != nil {
+		t.Fatalf("Setup: CreateApiDeployment(%+v) returned error: %s", createReq, err)
+	}
+
+	firstWant := &rpc.ApiDeployment{
+		Name:               fmt.Sprintf("%s@%s", firstRevision.GetName(), firstRevision.GetRevisionId()),
+		CreateTime:         firstRevision.GetCreateTime(),
+		RevisionCreateTime: firstRevision.GetRevisionCreateTime(),
+		RevisionUpdateTime: firstRevision.GetRevisionUpdateTime(),
+		RevisionId:         firstRevision.GetRevisionId(),
+	}
+
+	updateReq := &rpc.UpdateApiDeploymentRequest{
+		ApiDeployment: &rpc.ApiDeployment{
+			Name:            firstRevision.GetName(),
+			ApiSpecRevision: deploymentApiSpecRevision,
+		},
+	}
+
+	secondRevision, err := server.UpdateApiDeployment(ctx, updateReq)
+	if err != nil {
+		t.Fatalf("Setup: UpdateApiDeployment(%+v) returned error: %s", updateReq, err)
+	}
+
+	secondWant := &rpc.ApiDeployment{
+		Name:               fmt.Sprintf("%s@%s", secondRevision.GetName(), secondRevision.GetRevisionId()),
+		ApiSpecRevision:    deploymentApiSpecRevision,
+		CreateTime:         secondRevision.GetCreateTime(),
+		RevisionCreateTime: secondRevision.GetRevisionCreateTime(),
+		RevisionUpdateTime: secondRevision.GetRevisionUpdateTime(),
+		RevisionId:         secondRevision.GetRevisionId(),
+	}
+
+	opts := cmp.Options{
+		protocmp.Transform(),
+	}
+
+	var nextToken string
+	t.Run("first page", func(t *testing.T) {
+		req := &rpc.ListApiDeploymentRevisionsRequest{
+			Name:     firstRevision.GetName(),
+			PageSize: 1,
+		}
+
+		got, err := server.ListApiDeploymentRevisions(ctx, req)
+		if err != nil {
+			t.Fatalf("ListApiDeploymentRevisions(%+v) returned error: %s", req, err)
+		}
+
+		if count := len(got.GetApiDeployments()); count != 1 {
+			t.Errorf("ListApiDeploymentRevisions(%+v) returned %d specs, expected exactly one", req, count)
+		}
+
+		// Check that the most recent revision is returned.
+		want := []*rpc.ApiDeployment{secondWant}
+		if !cmp.Equal(want, got.GetApiDeployments(), opts) {
+			t.Errorf("List sequence returned unexpected diff (-want +got):\n%s", cmp.Diff(want, got.GetApiDeployments(), opts))
+		}
+
+		if got.GetNextPageToken() == "" {
+			t.Errorf("ListApiDeploymentRevisions(%+v) returned empty next_page_token, expected another page", req)
+		}
+
+		nextToken = got.GetNextPageToken()
+	})
+
+	if t.Failed() {
+		t.Fatal("Cannot test final page after failure on first page")
+	}
+
+	t.Run("final page", func(t *testing.T) {
+		req := &rpc.ListApiDeploymentRevisionsRequest{
+			Name:      firstRevision.GetName(),
+			PageToken: nextToken,
+		}
+
+		got, err := server.ListApiDeploymentRevisions(ctx, req)
+		if err != nil {
+			t.Fatalf("ListApiDeploymentRevisions(%+v) returned error: %s", req, err)
+		}
+
+		if count := len(got.GetApiDeployments()); count != 1 {
+			t.Errorf("ListApiDeploymentRevisions(%+v) returned %d specs, expected exactly one", req, count)
+		}
+
+		// Check that the original revision is returned.
+		want := []*rpc.ApiDeployment{firstWant}
+		if !cmp.Equal(want, got.GetApiDeployments(), opts) {
+			t.Errorf("List sequence returned unexpected diff (-want +got):\n%s", cmp.Diff(want, got.GetApiDeployments(), opts))
+		}
+
+		if got.GetNextPageToken() != "" {
+			t.Errorf("ListApiDeploymentRevisions(%+v) returned next_page_token, expected no next page", req)
+		}
+	})
+}
+
+func TestUpdateApiDeploymentRevisions(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	if err := seeder.SeedApis(ctx, server, &rpc.Api{Name: "projects/my-project/locations/global/apis/my-api"}); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	createReq := &rpc.CreateApiDeploymentRequest{
+		Parent:          "projects/my-project/locations/global/apis/my-api",
+		ApiDeploymentId: "my-spec",
+		ApiDeployment: &rpc.ApiDeployment{
+			Description: "Empty First Revision",
+		},
+	}
+
+	created, err := server.CreateApiDeployment(ctx, createReq)
+	if err != nil {
+		t.Fatalf("Setup: CreateApiDeployment(%+v) returned error: %s", createReq, err)
+	}
+
+	opts := cmp.Options{
+		protocmp.Transform(),
+		protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "create_time", "revision_create_time", "revision_update_time"),
+	}
+
+	t.Run("modify revision without content changes", func(t *testing.T) {
+		req := &rpc.UpdateApiDeploymentRequest{
+			ApiDeployment: &rpc.ApiDeployment{
+				Name: created.GetName(),
+			},
+		}
+
+		got, err := server.UpdateApiDeployment(ctx, req)
+		if err != nil {
+			t.Fatalf("UpdateApiDeployment(%+v) returned error: %s", req, err)
+		}
+
+		if got.GetRevisionId() != created.GetRevisionId() {
+			t.Errorf("UpdateApiDeployment(%+v) returned unexpected revision_id %q, expected no change (%q)", req, got.GetRevisionId(), created.GetRevisionId())
+		}
+
+		if ct, ut := got.GetRevisionCreateTime().AsTime(), got.GetRevisionUpdateTime().AsTime(); !ct.Before(ut) {
+			t.Errorf("UpdateApiDeployment(%+v) returned unexpected timestamps, expected revision_update_time %v > revision_create_time %v", req, ut, ct)
+		}
+	})
+
+	t.Run("modify revision with api_spec_revision changes", func(t *testing.T) {
+		req := &rpc.UpdateApiDeploymentRequest{
+			ApiDeployment: &rpc.ApiDeployment{
+				Name:            created.GetName(),
+				ApiSpecRevision: deploymentApiSpecRevision,
+			},
+		}
+		want := proto.Clone(created).(*rpc.ApiDeployment)
+		want.ApiSpecRevision = req.GetApiDeployment().GetApiSpecRevision()
+
+		got, err := server.UpdateApiDeployment(ctx, req)
+		if err != nil {
+			t.Fatalf("UpdateApiDeployment(%+v) returned error: %s", req, err)
+		}
+
+		if !cmp.Equal(want, got, opts) {
+			t.Errorf("UpdateApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(want, got, opts))
+		}
+
+		if got.GetRevisionId() == created.GetRevisionId() {
+			t.Errorf("UpdateApiDeployment(%+v) returned unexpected revision_id %q, expected new revision", req, got.GetRevisionId())
+		}
+
+		if ct, ut := got.GetCreateTime().AsTime(), got.GetRevisionUpdateTime().AsTime(); !ct.Before(ut) {
+			t.Errorf("UpdateApiDeployment(%+v) returned unexpected timestamps, expected revision_update_time %v > create_time %v", req, ut, ct)
+		}
+	})
+
+	t.Run("modify specific revision", func(t *testing.T) {
+		req := &rpc.UpdateApiDeploymentRequest{
+			ApiDeployment: &rpc.ApiDeployment{
+				Name: fmt.Sprintf("%s@%s", created.GetName(), created.GetRevisionId()),
+			},
+		}
+
+		if _, err := server.UpdateApiDeployment(ctx, req); status.Code(err) != codes.InvalidArgument {
+			t.Fatalf("UpdateApiDeployment(%+v) returned unexpected status code %q, want %q: %v", req, status.Code(err), codes.InvalidArgument, err)
+		}
+	})
+}
diff --git a/server/registry/actions_deployments_test.go b/server/registry/actions_deployments_test.go
new file mode 100644
index 0000000..439c11e
--- /dev/null
+++ b/server/registry/actions_deployments_test.go
@@ -0,0 +1,1106 @@
+// Copyright 2021 Google LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package registry
+
+import (
+	"context"
+	"fmt"
+	"testing"
+
+	"github.com/apigee/registry/rpc"
+	"github.com/apigee/registry/server/registry/internal/test/seeder"
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+	"google.golang.org/protobuf/testing/protocmp"
+	"google.golang.org/protobuf/types/known/fieldmaskpb"
+)
+
+func TestCreateApiDeployment(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.Api
+		req  *rpc.CreateApiDeploymentRequest
+		want *rpc.ApiDeployment
+	}{
+		{
+			desc: "fully populated resource",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "my-deployment",
+				ApiDeployment: &rpc.ApiDeployment{
+					Description: "My Description",
+					Labels: map[string]string{
+						"label-key": "label-value",
+					},
+					Annotations: map[string]string{
+						"annotation-key": "annotation-value",
+					},
+				},
+			},
+			want: &rpc.ApiDeployment{
+				Name:         "projects/my-project/locations/global/apis/a/deployments/my-deployment",
+				Description:  "My Description",
+				RevisionTags: []string{},
+				Labels: map[string]string{
+					"label-key": "label-value",
+				},
+				Annotations: map[string]string{
+					"annotation-key": "annotation-value",
+				},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedApis(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			created, err := server.CreateApiDeployment(ctx, test.req)
+			if err != nil {
+				t.Fatalf("CreateApiDeployment(%+v) returned error: %s", test.req, err)
+			}
+
+			opts := cmp.Options{
+				protocmp.Transform(),
+				protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "create_time", "revision_create_time", "revision_update_time"),
+			}
+
+			if !cmp.Equal(test.want, created, opts) {
+				t.Errorf("CreateApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", test.req, cmp.Diff(test.want, created, opts))
+			}
+
+			if created.RevisionId == "" {
+				t.Errorf("CreateApiDeployment(%+v) returned unexpected revision_id %q, expected non-empty ID", test.req, created.GetRevisionId())
+			}
+
+			if created.CreateTime == nil || created.RevisionCreateTime == nil || created.RevisionUpdateTime == nil {
+				t.Errorf("CreateApiDeployment(%+v) returned unset create_time (%v), revision_create_time (%v), or revision_update_time (%v)", test.req, created.CreateTime, created.RevisionCreateTime, created.RevisionUpdateTime)
+			} else if !created.CreateTime.AsTime().Equal(created.RevisionCreateTime.AsTime()) {
+				t.Errorf("CreateApiDeployment(%+v) returned unexpected timestamps: create_time %v != revision_create_time %v", test.req, created.CreateTime, created.RevisionCreateTime)
+			} else if !created.RevisionCreateTime.AsTime().Equal(created.RevisionUpdateTime.AsTime()) {
+				t.Errorf("CreateApiDeployment(%+v) returned unexpected timestamps: revision_create_time %v != revision_update_time %v", test.req, created.RevisionCreateTime, created.RevisionUpdateTime)
+			}
+
+			t.Run("GetApiDeployment", func(t *testing.T) {
+				req := &rpc.GetApiDeploymentRequest{
+					Name: created.GetName(),
+				}
+
+				got, err := server.GetApiDeployment(ctx, req)
+				if err != nil {
+					t.Fatalf("GetApiDeployment(%+v) returned error: %s", req, err)
+				}
+
+				opts := protocmp.Transform()
+				if !cmp.Equal(created, got, opts) {
+					t.Errorf("GetApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(created, got, opts))
+				}
+			})
+		})
+	}
+}
+
+func TestCreateApiDeploymentResponseCodes(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.Api
+		req  *rpc.CreateApiDeploymentRequest
+		want codes.Code
+	}{
+		{
+			desc: "parent not found",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a2",
+				ApiDeploymentId: "valid-id",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "missing resource body",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "valid-id",
+				ApiDeployment:   nil,
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "missing custom identifier",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "specific revision",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "my-spec@12345678",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "long custom identifier",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "this-identifier-is-invalid-because-it-exceeds-the-eighty-character-maximum-length",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "custom identifier underscores",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "underscore_identifier",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "custom identifier hyphen prefix",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "-identifier",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "custom identifier hyphen suffix",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "identifier-",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "customer identifier uuid format",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "072d2288-c685-42d8-9df0-5edbb2a809ea",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "customer identifier mixed case",
+			seed: &rpc.Api{Name: "projects/my-project/locations/global/apis/a"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "IDentifier",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedApis(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			if _, err := server.CreateApiDeployment(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("CreateApiDeployment(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
+
+func TestCreateApiDeploymentDuplicates(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.ApiDeployment
+		req  *rpc.CreateApiDeploymentRequest
+		want codes.Code
+	}{
+		{
+			desc: "case sensitive",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/my-deployment"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "my-deployment",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.AlreadyExists,
+		},
+		{
+			desc: "case insensitive",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/my-deployment"},
+			req: &rpc.CreateApiDeploymentRequest{
+				Parent:          "projects/my-project/locations/global/apis/a",
+				ApiDeploymentId: "My-Deployment",
+				ApiDeployment:   &rpc.ApiDeployment{},
+			},
+			want: codes.AlreadyExists,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			if _, err := server.CreateApiDeployment(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("CreateApiDeployment(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
+
+func TestGetApiDeployment(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.ApiDeployment
+		req  *rpc.GetApiDeploymentRequest
+		want *rpc.ApiDeployment
+	}{
+		{
+			desc: "fully populated resource",
+			seed: &rpc.ApiDeployment{
+				Name:        "projects/my-project/locations/global/apis/a/deployments/d",
+				Description: "My API Deployment",
+				Labels: map[string]string{
+					"label-key": "label-value",
+				},
+				Annotations: map[string]string{
+					"annotation-key": "annotation-value",
+				},
+			},
+			req: &rpc.GetApiDeploymentRequest{
+				Name: "projects/my-project/locations/global/apis/a/deployments/d",
+			},
+			want: &rpc.ApiDeployment{
+				Name:         "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:  "My API Deployment",
+				RevisionTags: []string{},
+				Labels: map[string]string{
+					"label-key": "label-value",
+				},
+				Annotations: map[string]string{
+					"annotation-key": "annotation-value",
+				},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			got, err := server.GetApiDeployment(ctx, test.req)
+			if err != nil {
+				t.Fatalf("GetApiDeployment(%+v) returned error: %s", test.req, err)
+			}
+
+			opts := cmp.Options{
+				protocmp.Transform(),
+				protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "create_time", "revision_create_time", "revision_update_time"),
+			}
+
+			if !cmp.Equal(test.want, got, opts) {
+				t.Errorf("GetApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", test.req, cmp.Diff(test.want, got, opts))
+			}
+		})
+	}
+}
+
+func TestGetApiDeploymentResponseCodes(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.ApiDeployment
+		req  *rpc.GetApiDeploymentRequest
+		want codes.Code
+	}{
+		{
+			desc: "resource not found",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req: &rpc.GetApiDeploymentRequest{
+				Name: "projects/my-project/locations/global/apis/a/deployments/doesnt-exist",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "case insensitive name",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req: &rpc.GetApiDeploymentRequest{
+				Name: "projects/my-project/locations/global/apis/a/deployments/D",
+			},
+			want: codes.OK,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			if _, err := server.GetApiDeployment(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("GetApiDeployment(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
+
+func TestListApiDeployments(t *testing.T) {
+	tests := []struct {
+		desc      string
+		seed      []*rpc.ApiDeployment
+		req       *rpc.ListApiDeploymentsRequest
+		want      *rpc.ListApiDeploymentsResponse
+		wantToken bool
+		extraOpts cmp.Option
+	}{
+		{
+			desc: "default parameters",
+			seed: []*rpc.ApiDeployment{
+				{Name: "projects/my-project/locations/global/apis/a1/deployments/d1"},
+				{Name: "projects/my-project/locations/global/apis/a1/deployments/d2"},
+				{Name: "projects/my-project/locations/global/apis/a1/deployments/d3"},
+				{Name: "projects/my-project/locations/global/apis/a2/deployments/d1"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/a1",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{Name: "projects/my-project/locations/global/apis/a1/deployments/d1"},
+					{Name: "projects/my-project/locations/global/apis/a1/deployments/d2"},
+					{Name: "projects/my-project/locations/global/apis/a1/deployments/d3"},
+				},
+			},
+		},
+		{
+			desc: "with specs containing multiple revisions",
+			seed: []*rpc.ApiDeployment{
+				{
+					Name: "projects/my-project/locations/global/apis/a1/deployments/d1",
+				},
+				{
+					Name:            "projects/my-project/locations/global/apis/a1/deployments/d1",
+					ApiSpecRevision: "some-revision",
+				},
+				{
+					Name: "projects/my-project/locations/global/apis/a1/deployments/d2",
+				},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/a1",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{
+						Name:            "projects/my-project/locations/global/apis/a1/deployments/d1",
+						ApiSpecRevision: "some-revision",
+					},
+					{
+						Name: "projects/my-project/locations/global/apis/a1/deployments/d2",
+					},
+				},
+			},
+		},
+		{
+			desc: "across all apis in a specific project",
+			seed: []*rpc.ApiDeployment{
+				{Name: "projects/my-project/locations/global/apis/a1/deployments/d"},
+				{Name: "projects/my-project/locations/global/apis/a2/deployments/d"},
+				{Name: "projects/other-project/locations/global/apis/a1/deployments/d"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/-",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{Name: "projects/my-project/locations/global/apis/a1/deployments/d"},
+					{Name: "projects/my-project/locations/global/apis/a2/deployments/d"},
+				},
+			},
+		},
+		{
+			desc: "across all projects and apis",
+			seed: []*rpc.ApiDeployment{
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+				{Name: "projects/other-project/locations/global/apis/other-api/deployments/d"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/-/locations/global/apis/-",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+					{Name: "projects/other-project/locations/global/apis/other-api/deployments/d"},
+				},
+			},
+		},
+		{
+			desc: "in a specific api across all projects",
+			seed: []*rpc.ApiDeployment{
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+				{Name: "projects/other-project/locations/global/apis/a/deployments/d"},
+				{Name: "projects/my-project/locations/global/apis/other-api/deployments/d"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/-/locations/global/apis/a",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+					{Name: "projects/other-project/locations/global/apis/a/deployments/d"},
+				},
+			},
+		},
+		{
+			desc: "custom page size",
+			seed: []*rpc.ApiDeployment{
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d1"},
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d2"},
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d3"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent:   "projects/my-project/locations/global/apis/a",
+				PageSize: 1,
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{},
+				},
+			},
+			wantToken: true,
+			// Ordering is not guaranteed by API, so any resource may be returned.
+			extraOpts: protocmp.IgnoreFields(new(rpc.ApiDeployment), "name"),
+		},
+		{
+			desc: "name equality filtering",
+			seed: []*rpc.ApiDeployment{
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d1"},
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d2"},
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d3"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/a",
+				Filter: "name == 'projects/my-project/locations/global/apis/a/deployments/d2'",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{Name: "projects/my-project/locations/global/apis/a/deployments/d2"},
+				},
+			},
+		},
+		{
+			desc: "description inequality filtering",
+			seed: []*rpc.ApiDeployment{
+				{
+					Name:        "projects/my-project/locations/global/apis/a/deployments/d1",
+					Description: "First ApiDeployment",
+				},
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d2"},
+				{Name: "projects/my-project/locations/global/apis/a/deployments/d3"},
+			},
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/a",
+				Filter: "description != ''",
+			},
+			want: &rpc.ListApiDeploymentsResponse{
+				ApiDeployments: []*rpc.ApiDeployment{
+					{
+						Name:        "projects/my-project/locations/global/apis/a/deployments/d1",
+						Description: "First ApiDeployment",
+					},
+				},
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed...); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			got, err := server.ListApiDeployments(ctx, test.req)
+			if err != nil {
+				t.Fatalf("ListApiDeployments(%+v) returned error: %s", test.req, err)
+			}
+
+			opts := cmp.Options{
+				protocmp.Transform(),
+				protocmp.IgnoreFields(new(rpc.ListApiDeploymentsResponse), "next_page_token"),
+				protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "create_time", "revision_create_time", "revision_update_time"),
+				protocmp.SortRepeated(func(a, b *rpc.ApiDeployment) bool {
+					return a.GetName() < b.GetName()
+				}),
+				test.extraOpts,
+			}
+
+			if !cmp.Equal(test.want, got, opts) {
+				t.Errorf("ListApiDeployments(%+v) returned unexpected diff (-want +got):\n%s", test.req, cmp.Diff(test.want, got, opts))
+			}
+
+			if test.wantToken && got.NextPageToken == "" {
+				t.Errorf("ListApiDeployments(%+v) returned empty next_page_token, expected non-empty next_page_token", test.req)
+			} else if !test.wantToken && got.NextPageToken != "" {
+				t.Errorf("ListApiDeployments(%+v) returned non-empty next_page_token, expected empty next_page_token: %s", test.req, got.GetNextPageToken())
+			}
+		})
+	}
+}
+
+func TestListApiDeploymentsResponseCodes(t *testing.T) {
+	tests := []struct {
+		desc string
+		req  *rpc.ListApiDeploymentsRequest
+		want codes.Code
+	}{
+		{
+			desc: "parent api not found",
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/a",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "parent project not found",
+			req: &rpc.ListApiDeploymentsRequest{
+				Parent: "projects/my-project/locations/global/apis/-",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "negative page size",
+			req: &rpc.ListApiDeploymentsRequest{
+				PageSize: -1,
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "invalid filter",
+			req: &rpc.ListApiDeploymentsRequest{
+				Filter: "this filter is not valid",
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "invalid page token",
+			req: &rpc.ListApiDeploymentsRequest{
+				PageToken: "this token is not valid",
+			},
+			want: codes.InvalidArgument,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+
+			if _, err := server.ListApiDeployments(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("ListApiDeployments(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
+
+func TestListApiDeploymentsSequence(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	seed := []*rpc.ApiDeployment{
+		{Name: "projects/my-project/locations/global/apis/a/deployments/d1"},
+		{Name: "projects/my-project/locations/global/apis/a/deployments/d2"},
+		{Name: "projects/my-project/locations/global/apis/a/deployments/d3"},
+	}
+	if err := seeder.SeedDeployments(ctx, server, seed...); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	listed := make([]*rpc.ApiDeployment, 0, 3)
+
+	var nextToken string
+	t.Run("first page", func(t *testing.T) {
+		req := &rpc.ListApiDeploymentsRequest{
+			Parent:   "projects/my-project/locations/global/apis/a",
+			PageSize: 1,
+		}
+
+		got, err := server.ListApiDeployments(ctx, req)
+		if err != nil {
+			t.Fatalf("ListApiDeployments(%+v) returned error: %s", req, err)
+		}
+
+		if count := len(got.GetApiDeployments()); count != 1 {
+			t.Errorf("ListApiDeployments(%+v) returned %d specs, expected exactly one", req, count)
+		}
+
+		if got.GetNextPageToken() == "" {
+			t.Errorf("ListApiDeployments(%+v) returned empty next_page_token, expected another page", req)
+		}
+
+		listed = append(listed, got.ApiDeployments...)
+		nextToken = got.GetNextPageToken()
+	})
+
+	if t.Failed() {
+		t.Fatal("Cannot test intermediate page after failure on first page")
+	}
+
+	t.Run("intermediate page", func(t *testing.T) {
+		req := &rpc.ListApiDeploymentsRequest{
+			Parent:    "projects/my-project/locations/global/apis/a",
+			PageSize:  1,
+			PageToken: nextToken,
+		}
+
+		got, err := server.ListApiDeployments(ctx, req)
+		if err != nil {
+			t.Fatalf("ListApiDeployments(%+v) returned error: %s", req, err)
+		}
+
+		if count := len(got.GetApiDeployments()); count != 1 {
+			t.Errorf("ListApiDeployments(%+v) returned %d specs, expected exactly one", req, count)
+		}
+
+		if got.GetNextPageToken() == "" {
+			t.Errorf("ListApiDeployments(%+v) returned empty next_page_token, expected another page", req)
+		}
+
+		listed = append(listed, got.ApiDeployments...)
+		nextToken = got.GetNextPageToken()
+	})
+
+	if t.Failed() {
+		t.Fatal("Cannot test final page after failure on intermediate page")
+	}
+
+	t.Run("final page", func(t *testing.T) {
+		req := &rpc.ListApiDeploymentsRequest{
+			Parent:    "projects/my-project/locations/global/apis/a",
+			PageSize:  1,
+			PageToken: nextToken,
+		}
+
+		got, err := server.ListApiDeployments(ctx, req)
+		if err != nil {
+			t.Fatalf("ListApiDeployments(%+v) returned error: %s", req, err)
+		}
+
+		if count := len(got.GetApiDeployments()); count != 1 {
+			t.Errorf("ListApiDeployments(%+v) returned %d specs, expected exactly one", req, count)
+		}
+
+		if got.GetNextPageToken() != "" {
+			t.Errorf("ListApiDeployments(%+v) returned next_page_token, expected no next page", req)
+		}
+
+		listed = append(listed, got.ApiDeployments...)
+	})
+
+	if t.Failed() {
+		t.Fatal("Cannot test sequence result after failure on final page")
+	}
+
+	opts := cmp.Options{
+		protocmp.Transform(),
+		protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "create_time", "revision_create_time", "revision_update_time"),
+		cmpopts.SortSlices(func(a, b *rpc.ApiDeployment) bool {
+			return a.GetName() < b.GetName()
+		}),
+	}
+
+	if !cmp.Equal(seed, listed, opts) {
+		t.Errorf("List sequence returned unexpected diff (-want +got):\n%s", cmp.Diff(seed, listed, opts))
+	}
+}
+
+// This test prevents the list sequence from ending before a known filter match is listed.
+// For simplicity, it does not guarantee the resource is returned on a later page.
+func TestListApiDeploymentsLargeCollectionFiltering(t *testing.T) {
+	ctx := context.Background()
+	server := defaultTestServer(t)
+	seed := make([]*rpc.ApiDeployment, 0, 100)
+	for i := 1; i <= cap(seed); i++ {
+		seed = append(seed, &rpc.ApiDeployment{
+			Name: fmt.Sprintf("projects/my-project/locations/global/apis/a/deployments/d%03d", i),
+		})
+	}
+
+	if err := seeder.SeedDeployments(ctx, server, seed...); err != nil {
+		t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+	}
+
+	req := &rpc.ListApiDeploymentsRequest{
+		Parent:   "projects/my-project/locations/global/apis/a",
+		PageSize: 1,
+		Filter:   "name == 'projects/my-project/locations/global/apis/a/deployments/d099'",
+	}
+
+	got, err := server.ListApiDeployments(ctx, req)
+	if err != nil {
+		t.Fatalf("ListApiDeployments(%+v) returned error: %s", req, err)
+	}
+
+	if len(got.GetApiDeployments()) == 1 && got.GetNextPageToken() != "" {
+		t.Errorf("ListApiDeployments(%+v) returned a page token when the only matching resource has been listed: %+v", req, got)
+	} else if len(got.GetApiDeployments()) == 0 && got.GetNextPageToken() == "" {
+		t.Errorf("ListApiDeployments(%+v) returned an empty next page token before listing the only matching resource", req)
+	} else if count := len(got.GetApiDeployments()); count > 1 {
+		t.Errorf("ListApiDeployments(%+v) returned %d projects, expected at most one: %+v", req, count, got.GetApiDeployments())
+	}
+}
+
+func TestUpdateApiDeployment(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.ApiDeployment
+		req  *rpc.UpdateApiDeploymentRequest
+		want *rpc.ApiDeployment
+	}{
+		{
+			desc: "allow missing updates existing resources",
+			seed: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name:        "projects/my-project/locations/global/apis/a/deployments/d",
+					Description: "My Updated ApiDeployment",
+				},
+				UpdateMask:   &fieldmaskpb.FieldMask{Paths: []string{"description"}},
+				AllowMissing: true,
+			},
+			want: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My Updated ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+		},
+		{
+			desc: "allow missing creates missing resources",
+			seed: &rpc.ApiDeployment{
+				Name: "projects/my-project/locations/global/apis/a/deployments/d-sibling",
+			},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name: "projects/my-project/locations/global/apis/a/deployments/d",
+				},
+				AllowMissing: true,
+			},
+			want: &rpc.ApiDeployment{
+				Name: "projects/my-project/locations/global/apis/a/deployments/d",
+			},
+		},
+		{
+			desc: "implicit nil mask",
+			seed: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name:        "projects/my-project/locations/global/apis/a/deployments/d",
+					Description: "My Updated ApiDeployment",
+				},
+			},
+			want: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My Updated ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+		},
+		{
+			desc: "implicit empty mask",
+			seed: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name:        "projects/my-project/locations/global/apis/a/deployments/d",
+					Description: "My Updated ApiDeployment",
+				},
+				UpdateMask: &fieldmaskpb.FieldMask{},
+			},
+			want: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My Updated ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+		},
+		{
+			desc: "field specific mask",
+			seed: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+					Description:    "My Updated ApiDeployment",
+					AccessGuidance: "Ignored",
+				},
+				UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"description"}},
+			},
+			want: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My Updated ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+		},
+		{
+			desc: "full replacement wildcard mask",
+			seed: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My ApiDeployment",
+				AccessGuidance: "openapi.json",
+			},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name:        "projects/my-project/locations/global/apis/a/deployments/d",
+					Description: "My Updated ApiDeployment",
+				},
+				UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"*"}},
+			},
+			want: &rpc.ApiDeployment{
+				Name:           "projects/my-project/locations/global/apis/a/deployments/d",
+				Description:    "My Updated ApiDeployment",
+				AccessGuidance: "",
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			updated, err := server.UpdateApiDeployment(ctx, test.req)
+			if err != nil {
+				t.Fatalf("UpdateApiDeployment(%+v) returned error: %s", test.req, err)
+			}
+
+			opts := cmp.Options{
+				protocmp.Transform(),
+				protocmp.IgnoreFields(new(rpc.ApiDeployment), "revision_id", "create_time", "revision_create_time", "revision_update_time"),
+			}
+
+			if !cmp.Equal(test.want, updated, opts) {
+				t.Errorf("UpdateApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", test.req, cmp.Diff(test.want, updated, opts))
+			}
+
+			t.Run("GetApiDeployment", func(t *testing.T) {
+				req := &rpc.GetApiDeploymentRequest{
+					Name: updated.GetName(),
+				}
+
+				got, err := server.GetApiDeployment(ctx, req)
+				if err != nil {
+					t.Fatalf("GetApiDeployment(%+v) returned error: %s", req, err)
+				}
+
+				opts := protocmp.Transform()
+				if !cmp.Equal(updated, got, opts) {
+					t.Errorf("GetApiDeployment(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(updated, got, opts))
+				}
+			})
+		})
+	}
+}
+
+func TestUpdateApiDeploymentResponseCodes(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.ApiDeployment
+		req  *rpc.UpdateApiDeploymentRequest
+		want codes.Code
+	}{
+		{
+			desc: "resource not found",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name: "projects/my-project/locations/global/apis/a/deployments/doesnt-exist",
+				},
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "specific revision",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name: "projects/my-project/locations/global/apis/a/versions/v1/deployments/d@12345678",
+				},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "missing resource body",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req:  &rpc.UpdateApiDeploymentRequest{},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "missing resource name",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{},
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "nonexistent field in mask",
+			seed: &rpc.ApiDeployment{Name: "projects/my-project/locations/global/apis/a/deployments/d"},
+			req: &rpc.UpdateApiDeploymentRequest{
+				ApiDeployment: &rpc.ApiDeployment{
+					Name: "projects/my-project/locations/global/apis/a/deployments/d",
+				},
+				UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"this field does not exist"}},
+			},
+			want: codes.InvalidArgument,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			if _, err := server.UpdateApiDeployment(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("UpdateApiDeployment(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
+
+func TestDeleteApiDeployment(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.ApiDeployment
+		req  *rpc.DeleteApiDeploymentRequest
+	}{
+		{
+			desc: "existing resource",
+			seed: &rpc.ApiDeployment{
+				Name: "projects/my-project/locations/global/apis/a/deployments/d",
+			},
+			req: &rpc.DeleteApiDeploymentRequest{
+				Name: "projects/my-project/locations/global/apis/a/deployments/d",
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedDeployments(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			if _, err := server.DeleteApiDeployment(ctx, test.req); err != nil {
+				t.Fatalf("DeleteApiDeployment(%+v) returned error: %s", test.req, err)
+			}
+
+			t.Run("GetApiDeployment", func(t *testing.T) {
+				req := &rpc.GetApiDeploymentRequest{
+					Name: test.req.GetName(),
+				}
+
+				if _, err := server.GetApiDeployment(ctx, req); status.Code(err) != codes.NotFound {
+					t.Fatalf("GetApiDeployment(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), codes.NotFound, err)
+				}
+			})
+		})
+	}
+}
+
+func TestDeleteApiDeploymentResponseCodes(t *testing.T) {
+	tests := []struct {
+		desc string
+		req  *rpc.DeleteApiDeploymentRequest
+		want codes.Code
+	}{
+		{
+			desc: "resource not found",
+			req: &rpc.DeleteApiDeploymentRequest{
+				Name: "projects/my-project/locations/global/apis/a/deployments/doesnt-exist",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "specific revision",
+			req: &rpc.DeleteApiDeploymentRequest{
+				Name: "projects/my-project/locations/global/apis/a/deployments/d@12345678",
+			},
+			want: codes.InvalidArgument,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+
+			if _, err := server.DeleteApiDeployment(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("DeleteApiDeployment(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
diff --git a/server/registry/actions_spec_revisions_test.go b/server/registry/actions_spec_revisions_test.go
index 83383ff..efe64ba 100644
--- a/server/registry/actions_spec_revisions_test.go
+++ b/server/registry/actions_spec_revisions_test.go
@@ -457,7 +457,7 @@ func TestUpdateApiSpecRevisions(t *testing.T) {
 		}
 
 		if !cmp.Equal(want, got, opts) {
-			t.Errorf("TagApiSpecRevision(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(want, got, opts))
+			t.Errorf("UpdateApiSpec(%+v) returned unexpected diff (-want +got):\n%s", req, cmp.Diff(want, got, opts))
 		}
 
 		if got.GetRevisionId() == created.GetRevisionId() {
diff --git a/server/registry/internal/test/seeder/seeder.go b/server/registry/internal/test/seeder/seeder.go
index 6bdf626..bbebee6 100644
--- a/server/registry/internal/test/seeder/seeder.go
+++ b/server/registry/internal/test/seeder/seeder.go
@@ -44,7 +44,7 @@ type RegistryResource interface {
 // Each revision can be tagged by providing a list of tags in the `revision_tags` field.
 //
 // Resource names must be unique with the exception of ApiSpec resources.
-// Supported resource types are Project, Api, ApiVersion, ApiSpec, and Artifact.
+// Supported resource types are Project, Api, ApiVersion, ApiSpec, ApiDeployment, and Artifact.
 func SeedRegistry(ctx context.Context, s RegistryImp, resources ...RegistryResource) error {
 	// All child resources are prefixed with their parent's name, so this sorts resources into hierarchical ordering.
 	// Using a stable sort keeps multiple resources of the same name in their original order.
@@ -84,6 +84,14 @@ func SeedRegistry(ctx context.Context, s RegistryImp, resources ...RegistryResou
 			if err := seedSpec(ctx, s, r, h); err != nil {
 				return err
 			}
+		case *rpc.ApiDeployment:
+			if h[r.GetName()] {
+				return fmt.Errorf("cannot seed multiple deployments with name %s", r.GetName())
+			}
+
+			if err := seedDeployment(ctx, s, r, h); err != nil {
+				return err
+			}
 		case *rpc.Artifact:
 			if h[r.GetName()] {
 				return fmt.Errorf("cannot seed multiple artifacts with name %s", r.GetName())
@@ -136,6 +144,15 @@ func SeedSpecs(ctx context.Context, s RegistryImp, specs ...*rpc.ApiSpec) error
 	return SeedRegistry(ctx, s, resources...)
 }
 
+// SeedDeployments is a convenience function for calling SeedRegistry with only ApiDeployment messages.
+func SeedDeployments(ctx context.Context, s RegistryImp, deployments ...*rpc.ApiDeployment) error {
+	resources := make([]RegistryResource, 0, len(deployments))
+	for _, r := range deployments {
+		resources = append(resources, r)
+	}
+	return SeedRegistry(ctx, s, resources...)
+}
+
 // SeedArtifacts is a convenience function for calling SeedRegistry with only Artifact messages.
 func SeedArtifacts(ctx context.Context, s RegistryImp, artifacts ...*rpc.Artifact) error {
 	resources := make([]RegistryResource, 0, len(artifacts))
@@ -260,6 +277,47 @@ func sha256hash(bytes []byte) string {
 	return fmt.Sprintf("%x", sha256.Sum256(bytes))
 }
 
+func seedDeployment(ctx context.Context, s RegistryImp, deployment *rpc.ApiDeployment, history map[string]bool) error {
+	signature := sha256hash([]byte(fmt.Sprintf("%s:%s", deployment.GetApiSpecRevision(), deployment.GetEndpointUri())))
+	if id := fmt.Sprintf("%s@%s", deployment.GetName(), signature); history[id] {
+		return nil
+	} else {
+		history[id] = true
+	}
+
+	name, err := names.ParseDeployment(deployment.GetName())
+	if err != nil {
+		return err
+	}
+
+	if err := seedApi(ctx, s, &rpc.Api{Name: name.Parent()}, history); err != nil {
+		return err
+	}
+
+	created, err := s.UpdateApiDeployment(ctx, &rpc.UpdateApiDeploymentRequest{
+		ApiDeployment: deployment,
+		UpdateMask:    &fieldmaskpb.FieldMask{Paths: []string{"*"}},
+		AllowMissing:  true,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	for _, tag := range deployment.RevisionTags {
+		_, err := s.TagApiDeploymentRevision(ctx, &rpc.TagApiDeploymentRevisionRequest{
+			Name: name.Revision(created.GetRevisionId()).String(),
+			Tag:  tag,
+		})
+
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 func seedArtifact(ctx context.Context, s RegistryImp, a *rpc.Artifact, history map[string]bool) error {
 	if id := a.GetName(); history[id] {
 		return nil
@@ -276,6 +334,8 @@ func seedArtifact(ctx context.Context, s RegistryImp, a *rpc.Artifact, history m
 		err = seedSpec(ctx, s, &rpc.ApiSpec{Name: name.Parent()}, history)
 	} else if name.VersionID() != "" {
 		err = seedVersion(ctx, s, &rpc.ApiVersion{Name: name.Parent()}, history)
+	} else if name.DeploymentID() != "" {
+		err = seedDeployment(ctx, s, &rpc.ApiDeployment{Name: name.Parent()}, history)
 	} else if name.ApiID() != "" {
 		err = seedApi(ctx, s, &rpc.Api{Name: name.Parent()}, history)
 	} else if name.ProjectID() != "" {
diff --git a/server/registry/internal/test/seeder/seeder_test.go b/server/registry/internal/test/seeder/seeder_test.go
index 55ba49a..9752ed8 100644
--- a/server/registry/internal/test/seeder/seeder_test.go
+++ b/server/registry/internal/test/seeder/seeder_test.go
@@ -60,6 +60,20 @@ func (s *fakeServer) TagApiSpecRevision(ctx context.Context, req *rpc.TagApiSpec
 	return nil, nil
 }
 
+func (s *fakeServer) UpdateApiDeployment(ctx context.Context, req *rpc.UpdateApiDeploymentRequest) (*rpc.ApiDeployment, error) {
+	s.Resources = append(s.Resources, req.ApiDeployment.GetName())
+	return &rpc.ApiDeployment{
+		Name:       req.ApiDeployment.GetName(),
+		RevisionId: fmt.Sprintf("%.8s", uuid.New().String()),
+	}, nil
+}
+
+func (s *fakeServer) TagApiDeploymentRevision(ctx context.Context, req *rpc.TagApiDeploymentRevisionRequest) (*rpc.ApiDeployment, error) {
+	tagged := fmt.Sprintf("%s@%s", strings.Split(req.GetName(), "@")[0], req.GetTag())
+	s.Resources = append(s.Resources, tagged)
+	return nil, nil
+}
+
 func (s *fakeServer) CreateArtifact(ctx context.Context, req *rpc.CreateArtifactRequest) (*rpc.Artifact, error) {
 	s.Resources = append(s.Resources, fmt.Sprintf("%s/artifacts/%s", req.GetParent(), req.GetArtifactId()))
 	return nil, nil
@@ -78,11 +92,13 @@ func TestSeedRegistry(t *testing.T) {
 				&rpc.Api{Name: "projects/p/locations/global/apis/a"},
 				&rpc.ApiVersion{Name: "projects/p/locations/global/apis/a/versions/v"},
 				&rpc.ApiSpec{Name: "projects/p/locations/global/apis/a/versions/v/specs/s"},
+				&rpc.ApiDeployment{Name: "projects/p/locations/global/apis/a/deployments/d"},
 				&rpc.Artifact{Name: "projects/p/locations/global/apis/a/versions/v/specs/s/artifacts/a"},
 			},
 			want: []string{
 				"projects/p",
 				"projects/p/locations/global/apis/a",
+				"projects/p/locations/global/apis/a/deployments/d",
 				"projects/p/locations/global/apis/a/versions/v",
 				"projects/p/locations/global/apis/a/versions/v/specs/s",
 				"projects/p/locations/global/apis/a/versions/v/specs/s/artifacts/a",
@@ -92,10 +108,13 @@ func TestSeedRegistry(t *testing.T) {
 			desc: "resources can be created implicitly",
 			seed: []RegistryResource{
 				&rpc.Artifact{Name: "projects/p/locations/global/apis/a/versions/v/specs/s/artifacts/a"},
+				&rpc.Artifact{Name: "projects/p/locations/global/apis/a/deployments/d/artifacts/a"},
 			},
 			want: []string{
 				"projects/p",
 				"projects/p/locations/global/apis/a",
+				"projects/p/locations/global/apis/a/deployments/d",
+				"projects/p/locations/global/apis/a/deployments/d/artifacts/a",
 				"projects/p/locations/global/apis/a/versions/v",
 				"projects/p/locations/global/apis/a/versions/v/specs/s",
 				"projects/p/locations/global/apis/a/versions/v/specs/s/artifacts/a",
@@ -104,6 +123,8 @@ func TestSeedRegistry(t *testing.T) {
 		{
 			desc: "resources can be created out of order",
 			seed: []RegistryResource{
+				&rpc.Artifact{Name: "projects/p/locations/global/apis/a/deployments/d/artifacts/a"},
+				&rpc.ApiDeployment{Name: "projects/p/locations/global/apis/a/deployments/d"},
 				&rpc.Artifact{Name: "projects/p/locations/global/apis/a/versions/v/specs/s/artifacts/a"},
 				&rpc.ApiSpec{Name: "projects/p/locations/global/apis/a/versions/v/specs/s"},
 				&rpc.ApiVersion{Name: "projects/p/locations/global/apis/a/versions/v"},
@@ -113,6 +134,8 @@ func TestSeedRegistry(t *testing.T) {
 			want: []string{
 				"projects/p",
 				"projects/p/locations/global/apis/a",
+				"projects/p/locations/global/apis/a/deployments/d",
+				"projects/p/locations/global/apis/a/deployments/d/artifacts/a",
 				"projects/p/locations/global/apis/a/versions/v",
 				"projects/p/locations/global/apis/a/versions/v/specs/s",
 				"projects/p/locations/global/apis/a/versions/v/specs/s/artifacts/a",
@@ -162,6 +185,48 @@ func TestSeedRegistry(t *testing.T) {
 				"projects/p/locations/global/apis/a/versions/v/specs/s@second-tag",
 			},
 		},
+		{
+			desc: "deployment revisions can be created when attributes change",
+			seed: []RegistryResource{
+				&rpc.ApiDeployment{
+					Name:            "projects/p/locations/global/apis/a/deployments/d",
+					ApiSpecRevision: "first",
+				},
+				&rpc.ApiDeployment{
+					Name:            "projects/p/locations/global/apis/a/deployments/d",
+					ApiSpecRevision: "first",
+				},
+				&rpc.ApiDeployment{
+					Name:            "projects/p/locations/global/apis/a/deployments/d",
+					ApiSpecRevision: "second",
+				},
+			},
+			want: []string{
+				"projects/p",
+				"projects/p/locations/global/apis/a",
+				"projects/p/locations/global/apis/a/deployments/d",
+				"projects/p/locations/global/apis/a/deployments/d",
+			},
+		},
+		{
+			desc: "deployment revision tags can be created",
+			seed: []RegistryResource{
+				&rpc.ApiDeployment{
+					Name: "projects/p/locations/global/apis/a/deployments/d",
+					RevisionTags: []string{
+						"first-tag",
+						"second-tag",
+					},
+				},
+			},
+			want: []string{
+				"projects/p",
+				"projects/p/locations/global/apis/a",
+				"projects/p/locations/global/apis/a/deployments/d",
+				"projects/p/locations/global/apis/a/deployments/d@first-tag",
+				"projects/p/locations/global/apis/a/deployments/d@second-tag",
+			},
+		},
 	}
 
 	for _, test := range tests {