diff --git a/docs/grpc/index.html b/docs/grpc/index.html
index 4aa7e20fed..bc6321af5d 100644
--- a/docs/grpc/index.html
+++ b/docs/grpc/index.html
@@ -3292,6 +3292,13 @@
RegisteredResource
|
+
+ | namespace |
+ Namespace |
+ |
+ |
+
+
| metadata |
common.Metadata |
@@ -13772,11 +13779,25 @@ CreateRegist
| values |
string |
repeated |
- Optional
+ | Optional
Registered Resource Values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character.
The stored value will be normalized to lower case. |
+
+ | namespace_id |
+ string |
+ |
+ |
+
+
+
+ | namespace_fqn |
+ string |
+ |
+ |
+
+
| metadata |
common.MetadataMutable |
@@ -14008,6 +14029,20 @@ GetRegisteredRe
|
+
+ | namespace_fqn |
+ string |
+ |
+ |
+
+
+
+ | namespace_id |
+ string |
+ |
+ |
+
+
@@ -14245,6 +14280,20 @@ ListRegistere
+
+ | namespace_id |
+ string |
+ |
+ |
+
+
+
+ | namespace_fqn |
+ string |
+ |
+ |
+
+
| pagination |
policy.PageRequest |
diff --git a/docs/openapi/policy/objects.openapi.yaml b/docs/openapi/policy/objects.openapi.yaml
index c1f082cc1a..361920e138 100644
--- a/docs/openapi/policy/objects.openapi.yaml
+++ b/docs/openapi/policy/objects.openapi.yaml
@@ -740,6 +740,9 @@ components:
items:
$ref: '#/components/schemas/policy.RegisteredResourceValue'
title: values
+ namespace:
+ title: namespace
+ $ref: '#/components/schemas/policy.Namespace'
metadata:
title: metadata
description: Common metadata
diff --git a/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml b/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
index 676ab81a2d..a11f21fb47 100644
--- a/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
+++ b/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
@@ -1049,6 +1049,9 @@ components:
items:
$ref: '#/components/schemas/policy.RegisteredResourceValue'
title: values
+ namespace:
+ title: namespace
+ $ref: '#/components/schemas/policy.Namespace'
metadata:
title: metadata
description: Common metadata
@@ -1379,7 +1382,19 @@ components:
uniqueItems: true
title: values
uniqueItems: true
- description: "Optional \n Registered Resource Values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character.\n The stored value will be normalized to lower case."
+ description: |-
+ Optional
+ Registered Resource Values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character.
+ The stored value will be normalized to lower case.
+ namespaceId:
+ type: string
+ title: namespace_id
+ format: uuid
+ namespaceFqn:
+ type: string
+ title: namespace_fqn
+ minLength: 1
+ format: uri
metadata:
title: metadata
description: |-
@@ -1505,6 +1520,16 @@ components:
title: name
required:
- name
+ properties:
+ namespaceFqn:
+ type: string
+ title: namespace_fqn
+ minLength: 1
+ format: uri
+ namespaceId:
+ type: string
+ title: namespace_id
+ format: uuid
title: GetRegisteredResourceRequest
additionalProperties: false
policy.registeredresources.GetRegisteredResourceResponse:
@@ -1619,6 +1644,15 @@ components:
policy.registeredresources.ListRegisteredResourcesRequest:
type: object
properties:
+ namespaceId:
+ type: string
+ title: namespace_id
+ format: uuid
+ namespaceFqn:
+ type: string
+ title: namespace_fqn
+ minLength: 1
+ format: uri
pagination:
title: pagination
description: Optional
diff --git a/lib/identifier/registered_resource_value.go b/lib/identifier/registered_resource_value.go
index f286853afd..5866903ce1 100644
--- a/lib/identifier/registered_resource_value.go
+++ b/lib/identifier/registered_resource_value.go
@@ -7,51 +7,80 @@ import (
)
type FullyQualifiedRegisteredResourceValue struct {
- Name string
- Value string
+ Namespace string
+ Name string
+ Value string
}
-// protovalidate already validates the FQN format in the service request
-// for parsing purposes, we can just look for any non-whitespace characters
-// e.g. should be in format of "https://reg_res//value/"
+// New FQN format: https:///reg_res//value/
var registeredResourceValueFqnRegex = regexp.MustCompile(
- `^https:\/\/reg_res\/(?[^\/]+)\/value\/(?[^\/]+)$`,
+ `^https:\/\/(?P[^\/]+)\/reg_res\/(?P[^\/]+)\/value\/(?P[^\/]+)$`,
)
-// parseRegisteredResourceValueFqn parses a registered resource value FQN string into a FullyQualifiedRegisteredResourceValue struct.
-// The FQN must be in the format: https://reg_res//value/
-func parseRegisteredResourceValueFqn(fqn string) (*FullyQualifiedRegisteredResourceValue, error) {
- matches := registeredResourceValueFqnRegex.FindStringSubmatch(fqn)
+// Legacy FQN format: https://reg_res//value/
+var legacyRegisteredResourceValueFqnRegex = regexp.MustCompile(
+ `^https:\/\/reg_res\/(?P[^\/]+)\/value\/(?P[^\/]+)$`,
+)
- // Check if we have matches first
+// matchFqnParts attempts to match fqn against re, extracts named groups, lowercases them,
+// and validates name/value with validObjectNameRegex. Returns nil if the regex doesn't match.
+func matchFqnParts(re *regexp.Regexp, fqn string, groups []string) (map[string]string, error) {
+ matches := re.FindStringSubmatch(fqn)
if len(matches) == 0 {
- return nil, fmt.Errorf("%w: FQN must be in format https://reg_res//value/", ErrInvalidFQNFormat)
+ return nil, nil //nolint:nilnil // nil means no match, not an error
}
+ result := make(map[string]string, len(groups))
+ for _, g := range groups {
+ idx := re.SubexpIndex(g)
+ if idx == -1 || idx >= len(matches) {
+ return nil, fmt.Errorf("%w: missing group %s", ErrInvalidFQNFormat, g)
+ }
+ result[g] = strings.ToLower(matches[idx])
+ }
+ if namespace, ok := result["namespace"]; ok {
+ if !validNamespaceRegex.MatchString(namespace) {
+ return nil, fmt.Errorf("%w: invalid namespace format %s", ErrInvalidFQNFormat, namespace)
+ }
+ }
+ name, value := result["name"], result["value"]
+ if !validObjectNameRegex.MatchString(name) || !validObjectNameRegex.MatchString(value) {
+ return nil, fmt.Errorf("%w: found name %s with value %s", ErrInvalidFQNFormat, name, value)
+ }
+ return result, nil
+}
- nameIdx := registeredResourceValueFqnRegex.SubexpIndex("name")
- valueIdx := registeredResourceValueFqnRegex.SubexpIndex("value")
-
- if nameIdx == -1 || valueIdx == -1 || len(matches) <= nameIdx || len(matches) <= valueIdx {
- return nil, fmt.Errorf("%w: valid FQN format of https://reg_res//value/ must be provided", ErrInvalidFQNFormat)
+// parseRegisteredResourceValueFqn parses a registered resource value FQN string into a FullyQualifiedRegisteredResourceValue struct.
+// Supports both the new format: https:///reg_res//value/
+// and the legacy format: https://reg_res//value/
+func parseRegisteredResourceValueFqn(fqn string) (*FullyQualifiedRegisteredResourceValue, error) {
+ // Try new format: https:///reg_res//value/
+ if parts, err := matchFqnParts(registeredResourceValueFqnRegex, fqn, []string{"namespace", "name", "value"}); err != nil {
+ return nil, err
+ } else if parts != nil {
+ return &FullyQualifiedRegisteredResourceValue{Namespace: parts["namespace"], Name: parts["name"], Value: parts["value"]}, nil
}
- name := strings.ToLower(matches[nameIdx])
- value := strings.ToLower(matches[valueIdx])
- isValid := validObjectNameRegex.MatchString(name) && validObjectNameRegex.MatchString(value)
- if !isValid {
- return nil, fmt.Errorf("%w: found name %s with value %s", ErrInvalidFQNFormat, name, value)
+ // Try legacy format: https://reg_res//value/
+ if parts, err := matchFqnParts(legacyRegisteredResourceValueFqnRegex, fqn, []string{"name", "value"}); err != nil {
+ return nil, err
+ } else if parts != nil {
+ return &FullyQualifiedRegisteredResourceValue{Name: parts["name"], Value: parts["value"]}, nil
}
- return &FullyQualifiedRegisteredResourceValue{
- Name: name,
- Value: value,
- }, nil
+ return nil, fmt.Errorf("%w: FQN must be in format https:///reg_res//value/", ErrInvalidFQNFormat)
}
// Implementing FullyQualified interface for FullyQualifiedRegisteredResourceValue
func (rrv *FullyQualifiedRegisteredResourceValue) FQN() string {
builder := strings.Builder{}
- builder.WriteString("https://reg_res/")
+ if rrv.Namespace != "" {
+ builder.WriteString("https://")
+ builder.WriteString(rrv.Namespace)
+ builder.WriteString("/reg_res/")
+ } else {
+ // Legacy format for backward compatibility
+ builder.WriteString("https://reg_res/")
+ }
builder.WriteString(rrv.Name)
builder.WriteString("/value/")
builder.WriteString(rrv.Value)
@@ -59,6 +88,9 @@ func (rrv *FullyQualifiedRegisteredResourceValue) FQN() string {
}
func (rrv *FullyQualifiedRegisteredResourceValue) Validate() error {
+ if rrv.Namespace != "" && !validNamespaceRegex.MatchString(rrv.Namespace) {
+ return fmt.Errorf("%w: invalid namespace format %s", ErrInvalidFQNFormat, rrv.Namespace)
+ }
if !validObjectNameRegex.MatchString(rrv.Name) {
return fmt.Errorf("%w: invalid resource name format %s", ErrInvalidFQNFormat, rrv.Name)
}
diff --git a/lib/identifier/registered_resource_value_test.go b/lib/identifier/registered_resource_value_test.go
index 8b3873b6de..d7c83f8a5a 100644
--- a/lib/identifier/registered_resource_value_test.go
+++ b/lib/identifier/registered_resource_value_test.go
@@ -8,48 +8,67 @@ import (
func TestRegisteredResourceValueFQN(t *testing.T) {
tests := []struct {
- name string
- resName string
- value string
- want string
+ name string
+ namespace string
+ resName string
+ value string
+ want string
}{
{
- name: "basic example",
- resName: "resource",
- value: "value",
- want: "https://reg_res/resource/value/value",
+ name: "namespaced basic example",
+ namespace: "example.com",
+ resName: "resource",
+ value: "value",
+ want: "https://example.com/reg_res/resource/value/value",
},
{
- name: "with hyphens",
- resName: "test-resource",
- value: "test-value",
- want: "https://reg_res/test-resource/value/test-value",
+ name: "namespaced with hyphens",
+ namespace: "example.com",
+ resName: "test-resource",
+ value: "test-value",
+ want: "https://example.com/reg_res/test-resource/value/test-value",
},
{
- name: "with underscores",
- resName: "test_resource",
- value: "test_value",
- want: "https://reg_res/test_resource/value/test_value",
+ name: "namespaced with underscores",
+ namespace: "example.com",
+ resName: "test_resource",
+ value: "test_value",
+ want: "https://example.com/reg_res/test_resource/value/test_value",
},
{
- name: "with numbers",
- resName: "resource123",
- value: "value456",
- want: "https://reg_res/resource123/value/value456",
+ name: "namespaced with numbers",
+ namespace: "example.com",
+ resName: "resource123",
+ value: "value456",
+ want: "https://example.com/reg_res/resource123/value/value456",
+ },
+ {
+ name: "namespaced lower case",
+ namespace: "EXAMPLE.COM",
+ resName: "RESOURCE",
+ value: "VALUE",
+ want: "https://example.com/reg_res/resource/value/value",
},
{
- name: "lower case",
- resName: "RESOURCE",
- value: "VALUE",
+ name: "legacy no namespace",
+ resName: "resource",
+ value: "value",
want: "https://reg_res/resource/value/value",
},
+ {
+ name: "legacy with hyphens",
+ resName: "test-resource",
+ value: "test-value",
+ want: "https://reg_res/test-resource/value/test-value",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rrv := &FullyQualifiedRegisteredResourceValue{
- Name: tt.resName,
- Value: tt.value,
+ Namespace: tt.namespace,
+ Name: tt.resName,
+ Value: tt.value,
}
got := rrv.FQN()
require.Equal(t, tt.want, got)
@@ -148,47 +167,91 @@ func TestRegisteredResourceValueValidate(t *testing.T) {
func TestParseRegisteredResourceValueFqn(t *testing.T) {
tests := []struct {
- name string
- fqn string
- wantName string
- wantValue string
- wantErr bool
+ name string
+ fqn string
+ wantNamespace string
+ wantName string
+ wantValue string
+ wantErr bool
}{
+ // New format tests
+ {
+ name: "valid namespaced basic",
+ fqn: "https://example.com/reg_res/valid/value/test",
+ wantNamespace: "example.com",
+ wantName: "valid",
+ wantValue: "test",
+ wantErr: false,
+ },
+ {
+ name: "valid namespaced with hyphens",
+ fqn: "https://example.com/reg_res/test-resource/value/test-value",
+ wantNamespace: "example.com",
+ wantName: "test-resource",
+ wantValue: "test-value",
+ wantErr: false,
+ },
+ {
+ name: "valid namespaced with underscores",
+ fqn: "https://example.com/reg_res/test_resource/value/test_value",
+ wantNamespace: "example.com",
+ wantName: "test_resource",
+ wantValue: "test_value",
+ wantErr: false,
+ },
{
- name: "valid basic",
+ name: "valid namespaced with numbers",
+ fqn: "https://example.com/reg_res/resource123/value/value456",
+ wantNamespace: "example.com",
+ wantName: "resource123",
+ wantValue: "value456",
+ wantErr: false,
+ },
+ {
+ name: "valid namespaced lower case",
+ fqn: "https://EXAMPLE.COM/reg_res/RESOURce/value/valUE",
+ wantNamespace: "example.com",
+ wantName: "resource",
+ wantValue: "value",
+ wantErr: false,
+ },
+ // Legacy format tests
+ {
+ name: "valid legacy basic",
fqn: "https://reg_res/valid/value/test",
wantName: "valid",
wantValue: "test",
wantErr: false,
},
{
- name: "valid with hyphens",
+ name: "valid legacy with hyphens",
fqn: "https://reg_res/test-resource/value/test-value",
wantName: "test-resource",
wantValue: "test-value",
wantErr: false,
},
{
- name: "valid with underscores",
+ name: "valid legacy with underscores",
fqn: "https://reg_res/test_resource/value/test_value",
wantName: "test_resource",
wantValue: "test_value",
wantErr: false,
},
{
- name: "valid with numbers",
+ name: "valid legacy with numbers",
fqn: "https://reg_res/resource123/value/value456",
wantName: "resource123",
wantValue: "value456",
wantErr: false,
},
{
- name: "valid lower case",
+ name: "valid legacy lower case",
fqn: "https://reg_res/RESOURce/value/valUE",
wantName: "resource",
wantValue: "value",
wantErr: false,
},
+ // Invalid format tests
{
name: "empty string",
fqn: "",
@@ -199,29 +262,29 @@ func TestParseRegisteredResourceValueFqn(t *testing.T) {
fqn: "invalid",
wantErr: true,
},
- {
- name: "wrong prefix",
- fqn: "https://registered/valid/value/test",
- wantErr: true,
- },
{
name: "missing parts",
- fqn: "https://reg_res/valid",
+ fqn: "https://example.com/reg_res/valid",
wantErr: true,
},
{
name: "missing value segment",
- fqn: "https://reg_res/valid/value",
+ fqn: "https://example.com/reg_res/valid/value",
wantErr: true,
},
{
name: "wrong protocol",
- fqn: "http://reg_res/test/value/something",
+ fqn: "http://example.com/reg_res/test/value/something",
wantErr: true,
},
{
name: "extra prefix",
- fqn: "somethinghttps://reg_res/test/value/something",
+ fqn: "somethinghttps://example.com/reg_res/test/value/something",
+ wantErr: true,
+ },
+ {
+ name: "invalid namespace format",
+ fqn: "https://not_a_valid_namespace/reg_res/test/value/something",
wantErr: true,
},
}
@@ -236,6 +299,7 @@ func TestParseRegisteredResourceValueFqn(t *testing.T) {
if tt.wantErr {
return
}
+ require.Equal(t, tt.wantNamespace, got.Namespace)
require.Equal(t, tt.wantName, got.Name)
require.Equal(t, tt.wantValue, got.Value)
})
@@ -245,29 +309,44 @@ func TestParseRegisteredResourceValueFqn(t *testing.T) {
func TestRegisteredResourceValueRoundTrip(t *testing.T) {
// Test round trip from struct to FQN to parse and back
tests := []struct {
- name string
- resName string
- value string
+ name string
+ namespace string
+ resName string
+ value string
}{
{
- name: "basic example",
- resName: "resource",
- value: "value",
+ name: "namespaced basic example",
+ namespace: "example.com",
+ resName: "resource",
+ value: "value",
},
{
- name: "with hyphens",
- resName: "test-resource",
- value: "test-value",
+ name: "namespaced with hyphens",
+ namespace: "example.com",
+ resName: "test-resource",
+ value: "test-value",
},
{
- name: "with underscores",
- resName: "test_resource",
- value: "test_value",
+ name: "namespaced with underscores",
+ namespace: "my.namespace.org",
+ resName: "test_resource",
+ value: "test_value",
},
{
- name: "with numbers",
- resName: "resource123",
- value: "value456",
+ name: "namespaced with numbers",
+ namespace: "example.com",
+ resName: "resource123",
+ value: "value456",
+ },
+ {
+ name: "legacy basic example",
+ resName: "resource",
+ value: "value",
+ },
+ {
+ name: "legacy with hyphens",
+ resName: "test-resource",
+ value: "test-value",
},
}
@@ -275,8 +354,9 @@ func TestRegisteredResourceValueRoundTrip(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
// Create original registered resource value
original := &FullyQualifiedRegisteredResourceValue{
- Name: tt.resName,
- Value: tt.value,
+ Namespace: tt.namespace,
+ Name: tt.resName,
+ Value: tt.value,
}
// Get FQN
@@ -287,6 +367,7 @@ func TestRegisteredResourceValueRoundTrip(t *testing.T) {
require.NoError(t, err)
// Check the parsed values match original
+ require.Equal(t, original.Namespace, parsed.Namespace)
require.Equal(t, original.Name, parsed.Name)
require.Equal(t, original.Value, parsed.Value)
diff --git a/protocol/go/policy/registeredresources/registered_resources.pb.go b/protocol/go/policy/registeredresources/registered_resources.pb.go
index 93b33efca5..9f31448e6a 100644
--- a/protocol/go/policy/registeredresources/registered_resources.pb.go
+++ b/protocol/go/policy/registeredresources/registered_resources.pb.go
@@ -164,9 +164,9 @@ type GetRegisteredResourceRequest struct {
//
// *GetRegisteredResourceRequest_Id
// *GetRegisteredResourceRequest_Name
- Identifier isGetRegisteredResourceRequest_Identifier `protobuf_oneof:"identifier"`
- // Optional - namespace context for name-based lookups (since names are not globally unique for namespaced RRs)
- NamespaceFqn string `protobuf:"bytes,3,opt,name=namespace_fqn,json=namespaceFqn,proto3" json:"namespace_fqn,omitempty"`
+ Identifier isGetRegisteredResourceRequest_Identifier `protobuf_oneof:"identifier"`
+ NamespaceFqn string `protobuf:"bytes,3,opt,name=namespace_fqn,json=namespaceFqn,proto3" json:"namespace_fqn,omitempty"`
+ NamespaceId string `protobuf:"bytes,4,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"`
}
func (x *GetRegisteredResourceRequest) Reset() {
@@ -229,6 +229,13 @@ func (x *GetRegisteredResourceRequest) GetNamespaceFqn() string {
return ""
}
+func (x *GetRegisteredResourceRequest) GetNamespaceId() string {
+ if x != nil {
+ return x.NamespaceId
+ }
+ return ""
+}
+
type isGetRegisteredResourceRequest_Identifier interface {
isGetRegisteredResourceRequest_Identifier()
}
@@ -1500,7 +1507,7 @@ var file_policy_registeredresources_registered_resources_proto_rawDesc = []byte{
0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22,
- 0xaa, 0x04, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x98, 0x04, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x1a, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0xc2, 0x02, 0x0a,
@@ -1524,136 +1531,238 @@ var file_policy_registeredresources_registered_resources_proto_rawDesc = []byte{
0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d,
0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x20, 0x3a, 0x20, 0x74, 0x72, 0x75,
0x65, 0xc8, 0x01, 0x00, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x12, 0x93, 0x01, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
- 0x66, 0x71, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6e, 0xba, 0x48, 0x6b, 0xba, 0x01,
- 0x68, 0x0a, 0x16, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x66, 0x71, 0x6e, 0x12, 0x2d, 0x4e, 0x61, 0x6d, 0x65, 0x73,
- 0x70, 0x61, 0x63, 0x65, 0x20, 0x46, 0x51, 0x4e, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65,
- 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x52, 0x49, 0x20, 0x69, 0x66, 0x20,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x1a, 0x1f, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74,
- 0x68, 0x69, 0x73, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69,
- 0x73, 0x2e, 0x69, 0x73, 0x55, 0x72, 0x69, 0x28, 0x29, 0x52, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73,
- 0x70, 0x61, 0x63, 0x65, 0x46, 0x71, 0x6e, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74,
- 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x57, 0x0a, 0x1d,
- 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a,
- 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+ 0x65, 0x12, 0x2f, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x66,
+ 0x71, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10,
+ 0x01, 0x88, 0x01, 0x01, 0x52, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x46,
+ 0x71, 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
+ 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0,
+ 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x3a,
+ 0x24, 0xba, 0x48, 0x21, 0x22, 0x1f, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
+ 0x65, 0x5f, 0x69, 0x64, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
+ 0x66, 0x71, 0x6e, 0x10, 0x00, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66,
+ 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x57, 0x0a, 0x1d, 0x47, 0x65,
+ 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x72,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
+ 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
+ 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
+ 0x5f, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72,
+ 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x52, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
+ 0x65, 0x46, 0x71, 0x6e, 0x12, 0x33, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
+ 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70,
+ 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x24, 0xba, 0x48, 0x21, 0x22, 0x1f,
+ 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x0a, 0x0d,
+ 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x66, 0x71, 0x6e, 0x10, 0x00, 0x22,
+ 0x91, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x34, 0x0a,
+ 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x22, 0x89, 0x04, 0x0a, 0x1f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08,
- 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
- 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x5f, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48,
- 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x52, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
- 0x61, 0x63, 0x65, 0x46, 0x71, 0x6e, 0x12, 0x33, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
- 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x24, 0xba, 0x48, 0x21,
- 0x22, 0x1f, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64,
- 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x66, 0x71, 0x6e, 0x10,
- 0x00, 0x22, 0x91, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69,
+ 0x64, 0x12, 0xc0, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x42, 0xab, 0x02, 0xba, 0x48, 0xa7, 0x02, 0xba, 0x01, 0x9b, 0x02, 0x0a, 0x0e, 0x72, 0x72, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01, 0x52, 0x65,
+ 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61,
+ 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73,
+ 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20,
+ 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65,
+ 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20,
+ 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65,
+ 0x2e, 0x1a, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20,
+ 0x30, 0x20, 0x3f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73,
+ 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f,
+ 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b,
+ 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x20,
+ 0x3a, 0x20, 0x74, 0x72, 0x75, 0x65, 0xc8, 0x01, 0x00, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
+ 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52,
+ 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68,
+ 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+ 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22,
+ 0x5a, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52,
+ 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x3b, 0x0a, 0x1f, 0x44,
+ 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
+ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72,
+ 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5a, 0x0a, 0x20, 0x44, 0x65, 0x6c, 0x65,
+ 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08,
+ 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x22, 0xad, 0x04, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a,
+ 0x09, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x08, 0x61, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0xb2, 0x02, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x8e, 0x02, 0xba,
+ 0x48, 0x8a, 0x02, 0xba, 0x01, 0x81, 0x02, 0x0a, 0x12, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xad, 0x01, 0x41, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69,
+ 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69,
+ 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20,
+ 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65,
+ 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69,
+ 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a,
+ 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d,
+ 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30,
+ 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x48, 0x00, 0x52,
+ 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x12, 0x61,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69,
+ 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01,
+ 0x01, 0x48, 0x01, 0x52, 0x10, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x13, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x71, 0x6e, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x48, 0x01,
+ 0x52, 0x11, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x46, 0x71, 0x6e, 0x42, 0x1a, 0x0a, 0x11, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64,
+ 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x42,
+ 0x23, 0x0a, 0x1a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba,
+ 0x48, 0x02, 0x08, 0x01, 0x22, 0xa0, 0x04, 0x0a, 0x24, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52,
+ 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a,
+ 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x72, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0xad, 0x02, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x96, 0x02, 0xba, 0x48, 0x92, 0x02, 0xba,
+ 0x01, 0x86, 0x02, 0x0a, 0x0f, 0x72, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x6f,
+ 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, 0x01, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68,
+ 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e,
+ 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65,
+ 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63,
+ 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74,
+ 0x6f, 0x72, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74, 0x68,
+ 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d,
+ 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41,
+ 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a,
+ 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0xc8, 0x01, 0x01, 0x72, 0x03, 0x18, 0xfd,
+ 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x61, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
+ 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x61, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x08, 0x6d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5e, 0x0a, 0x25, 0x43, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x74, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x52, 0x65,
+ 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x02,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0,
+ 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01,
+ 0x01, 0x48, 0x00, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e,
+ 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x5b, 0x0a,
+ 0x22, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x53, 0x0a, 0x28, 0x47, 0x65,
+ 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e, 0x73, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x09, 0x42, 0x13, 0xba, 0x48, 0x10, 0x92, 0x01, 0x0d, 0x08, 0x01, 0x18, 0x01,
+ 0x22, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x52, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x22,
+ 0x88, 0x02, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42,
+ 0x79, 0x46, 0x51, 0x4e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a,
+ 0x0d, 0x66, 0x71, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x56, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65,
+ 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46,
+ 0x51, 0x4e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x71, 0x6e, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x66, 0x71,
+ 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x1a, 0x5f, 0x0a, 0x10, 0x46, 0x71, 0x6e,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
+ 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
+ 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2, 0x02, 0x0a, 0x23, 0x4c,
+ 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0xd5, 0x01, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0xb3, 0x01, 0xba, 0x48, 0xaf, 0x01, 0xba,
+ 0x01, 0xab, 0x01, 0x0a, 0x14, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x75,
+ 0x69, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x23, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x55, 0x49, 0x44, 0x1a, 0x6e,
+ 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20,
+ 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28,
+ 0x27, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x38, 0x7d, 0x2d,
+ 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, 0x2d, 0x5b,
+ 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, 0x2d, 0x5b, 0x30,
+ 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, 0x2d, 0x5b, 0x30, 0x2d,
+ 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x31, 0x32, 0x7d, 0x27, 0x29, 0x52, 0x0a,
+ 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x0a, 0x70, 0x61,
+ 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22,
+ 0x95, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12,
- 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67,
- 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x89, 0x04, 0x0a, 0x1f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52,
- 0x02, 0x69, 0x64, 0x12, 0xc0, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x42, 0xab, 0x02, 0xba, 0x48, 0xa7, 0x02, 0xba, 0x01, 0x9b, 0x02, 0x0a, 0x0e, 0x72,
- 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65,
- 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e,
- 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
- 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f,
- 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f,
- 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72,
- 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x61, 0x6d,
- 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c,
- 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61,
- 0x73, 0x65, 0x2e, 0x1a, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20,
- 0x3e, 0x20, 0x30, 0x20, 0x3f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68,
- 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d,
- 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d,
- 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27,
- 0x29, 0x20, 0x3a, 0x20, 0x74, 0x72, 0x75, 0x65, 0xc8, 0x01, 0x00, 0x72, 0x03, 0x18, 0xfd, 0x01,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
- 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c,
- 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x18, 0x6d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62,
- 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e,
- 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f,
- 0x72, 0x22, 0x5a, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
- 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x3b, 0x0a,
- 0x1f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
- 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50,
+ 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xfd, 0x04, 0x0a, 0x24, 0x55, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
- 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5a, 0x0a, 0x20, 0x44, 0x65,
- 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36,
- 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xad, 0x04, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x6f,
- 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
- 0x27, 0x0a, 0x09, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x08,
- 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0xb2, 0x02, 0x0a, 0x0b, 0x61, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x8e,
- 0x02, 0xba, 0x48, 0x8a, 0x02, 0xba, 0x01, 0x81, 0x02, 0x0a, 0x12, 0x61, 0x63, 0x74, 0x69, 0x6f,
- 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xad, 0x01,
- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74,
- 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f,
- 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64,
- 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74,
- 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73,
- 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63,
- 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20,
- 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
- 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74,
- 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74,
- 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61,
- 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a,
- 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d,
- 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x48,
- 0x00, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a,
- 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03,
- 0xb0, 0x01, 0x01, 0x48, 0x01, 0x52, 0x10, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x13, 0x61, 0x74, 0x74, 0x72, 0x69,
- 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x71, 0x6e, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01,
- 0x48, 0x01, 0x52, 0x11, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x46, 0x71, 0x6e, 0x42, 0x1a, 0x0a, 0x11, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
- 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08,
- 0x01, 0x42, 0x23, 0x0a, 0x1a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12,
- 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0xa0, 0x04, 0x0a, 0x24, 0x43, 0x72, 0x65, 0x61, 0x74,
- 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x29, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a,
- 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0xad, 0x02, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x96, 0x02, 0xba, 0x48, 0x92,
- 0x02, 0xba, 0x01, 0x86, 0x02, 0x0a, 0x0f, 0x72, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f,
+ 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xc5, 0x02, 0x0a, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0xae, 0x02, 0xba, 0x48, 0xaa,
+ 0x02, 0xba, 0x01, 0x9e, 0x02, 0x0a, 0x0f, 0x72, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f,
0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, 0x01, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x65, 0x64, 0x20, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c,
@@ -1665,278 +1774,175 @@ var file_policy_registeredresources_registered_resources_proto_rawDesc = []byte{
0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20,
0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c,
0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20,
- 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b,
- 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b,
- 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d,
- 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41,
- 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0xc8, 0x01, 0x01, 0x72, 0x03,
- 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x61, 0x63,
- 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x6f,
- 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41,
- 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x61,
- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
- 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52,
- 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5e, 0x0a, 0x25, 0x43, 0x72, 0x65,
- 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
+ 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x53,
+ 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x3f,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e,
+ 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61,
+ 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a,
+ 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x20, 0x3a, 0x20, 0x74,
+ 0x72, 0x75, 0x65, 0xc8, 0x01, 0x00, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+ 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x08,
+ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+ 0x61, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20,
+ 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+ 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42,
+ 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x5e, 0x0a, 0x25, 0x55, 0x70, 0x64, 0x61, 0x74,
+ 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x40, 0x0a, 0x24, 0x44, 0x65, 0x6c, 0x65, 0x74,
+ 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05,
+ 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5e, 0x0a, 0x25, 0x44, 0x65, 0x6c,
+ 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x74, 0x0a, 0x21, 0x47, 0x65, 0x74,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a,
- 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72,
- 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x03, 0x66, 0x71,
- 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01,
- 0x88, 0x01, 0x01, 0x48, 0x00, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64,
- 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22,
- 0x5b, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65,
+ 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x88, 0x0e, 0x0a, 0x1a, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x53, 0x0a, 0x28,
- 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e,
- 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x04, 0x66, 0x71, 0x6e, 0x73,
- 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x13, 0xba, 0x48, 0x10, 0x92, 0x01, 0x0d, 0x08, 0x01,
- 0x18, 0x01, 0x22, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x52, 0x04, 0x66, 0x71, 0x6e,
- 0x73, 0x22, 0x88, 0x02, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
- 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x7a, 0x0a, 0x0d, 0x66, 0x71, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6d, 0x61, 0x70,
- 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x56, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72,
+ 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e,
+ 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x22, 0x00, 0x12, 0x8e, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
+ 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x38, 0x2e, 0x70,
+ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
- 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42,
- 0x79, 0x46, 0x51, 0x4e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x71,
- 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b,
- 0x66, 0x71, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x1a, 0x5f, 0x0a, 0x10, 0x46,
- 0x71, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
- 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
- 0x79, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2, 0x02, 0x0a,
- 0x23, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x12, 0xd5, 0x01, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0xb3, 0x01, 0xba, 0x48, 0xaf,
- 0x01, 0xba, 0x01, 0xab, 0x01, 0x0a, 0x14, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f,
- 0x75, 0x75, 0x69, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x23, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74,
- 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x55, 0x49, 0x44,
- 0x1a, 0x6e, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3d, 0x3d, 0x20,
- 0x30, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65,
- 0x73, 0x28, 0x27, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x38,
- 0x7d, 0x2d, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d,
- 0x2d, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, 0x2d,
- 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, 0x2d, 0x5b,
- 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x31, 0x32, 0x7d, 0x27, 0x29,
- 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x0a,
- 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x13, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x22, 0x95, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
- 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70,
- 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xfd, 0x04, 0x0a, 0x24, 0x55, 0x70,
- 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08,
- 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xc5, 0x02, 0x0a,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0xae, 0x02, 0xba,
- 0x48, 0xaa, 0x02, 0xba, 0x01, 0x9e, 0x02, 0x0a, 0x0f, 0x72, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, 0x01, 0x52, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20,
- 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72,
- 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79,
- 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73,
- 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73,
- 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61,
- 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68,
- 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77,
- 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65,
- 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e,
- 0x1a, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30,
- 0x20, 0x3f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28,
- 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a,
- 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61,
- 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x20, 0x3a,
- 0x20, 0x74, 0x72, 0x75, 0x65, 0xc8, 0x01, 0x00, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61,
- 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18,
- 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72,
- 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
- 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41,
- 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x33,
- 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f,
- 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18,
- 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75,
- 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74,
- 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x5e, 0x0a, 0x25, 0x55, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x40, 0x0a, 0x24, 0x44, 0x65, 0x6c,
- 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba,
- 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5e, 0x0a, 0x25, 0x44,
- 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67,
- 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x88, 0x0e, 0x0a, 0x1a,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x18, 0x43,
- 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
+ 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x22, 0x00, 0x12, 0x94, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12,
+ 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73,
+ 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f,
+ 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a, 0x18, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73,
+ 0x72, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x00, 0x12, 0x8e, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69,
- 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x38,
+ 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
+ 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x12, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x44,
+ 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c,
0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
- 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52,
+ 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65,
+ 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa6,
+ 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x12, 0x40, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
+ 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e,
+ 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x9d, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
- 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x94, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72,
+ 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xb2, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x52,
+ 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e, 0x73, 0x12, 0x44, 0x2e,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x73, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c,
- 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e, 0x73, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x1a, 0x45, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+ 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51,
+ 0x4e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa3, 0x01, 0x0a,
+ 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x3f, 0x2e,
0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a,
- 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
- 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
- 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67,
- 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
- 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74,
- 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x12, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67,
- 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
- 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
- 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65,
- 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
- 0x12, 0xa6, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x12, 0x40, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69,
- 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e,
- 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74,
+ 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x22, 0x00, 0x12, 0xa6, 0x01, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
- 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x9d, 0x01, 0x0a, 0x1a, 0x47, 0x65,
- 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
- 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
- 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+ 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xb2, 0x01, 0x0a, 0x21, 0x47, 0x65,
- 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e, 0x73, 0x12,
- 0x44, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x51, 0x4e, 0x73, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x45, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72,
- 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79,
- 0x46, 0x51, 0x4e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa3,
- 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
- 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12,
- 0x3f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73,
- 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x40, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69,
- 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x00, 0x12, 0xa6, 0x01, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
- 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
- 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69,
- 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa6, 0x01,
- 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
- 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
- 0x40, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa6, 0x01, 0x0a, 0x1d,
+ 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x2e,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
+ 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x41, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x41, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x44,
- 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x87, 0x02, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x70,
- 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73,
- 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x50, 0x72,
- 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
- 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
- 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70,
- 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x52, 0x58, 0xaa,
- 0x02, 0x1a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
- 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0xca, 0x02, 0x1a, 0x50,
- 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0xe2, 0x02, 0x26, 0x50, 0x6f, 0x6c, 0x69,
- 0x63, 0x79, 0x5c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0xea, 0x02, 0x1b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x52, 0x65, 0x67,
- 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x22, 0x00, 0x42, 0x87, 0x02, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c,
+ 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x50, 0x01, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c,
+ 0x69, 0x63, 0x79, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x52, 0x58, 0xaa, 0x02, 0x1a,
+ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0xca, 0x02, 0x1a, 0x50, 0x6f, 0x6c,
+ 0x69, 0x63, 0x79, 0x5c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0xe2, 0x02, 0x26, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79,
+ 0x5c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0xea, 0x02, 0x1b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x52, 0x65, 0x67, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x65, 0x64, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/service/integration/registered_resources_test.go b/service/integration/registered_resources_test.go
index 789118fe98..2f910b9d54 100644
--- a/service/integration/registered_resources_test.go
+++ b/service/integration/registered_resources_test.go
@@ -61,17 +61,21 @@ const invalidID = "00000000-0000-0000-0000-000000000000"
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_Succeeds() {
req := ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res",
}
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, req)
s.Require().NoError(err)
s.NotNil(created)
+ s.NotNil(created.GetNamespace())
+ s.Equal(s.getNamespaceID("example.com"), created.GetNamespace().GetId())
}
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_NormalizedName_Succeeds() {
req := ®isteredresources.CreateRegisteredResourceRequest{
- Name: "TeST_CrEaTe_RES_NorMa-LiZeD",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "TeST_CrEaTe_RES_NorMa-LiZeD",
}
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, req)
@@ -86,8 +90,9 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithValues_Succ
"test_create_res_values__value2",
}
req := ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_values",
- Values: values,
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_values",
+ Values: values,
}
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, req)
@@ -101,7 +106,8 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithValues_Succ
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithMetadata_Succeeds() {
req := ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_metadata",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_metadata",
Metadata: &common.MetadataMutable{
Labels: map[string]string{
"key1": "value1",
@@ -116,16 +122,27 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithMetadata_Su
s.Require().Len(created.GetMetadata().GetLabels(), 2)
}
-func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithNonUniqueName_Fails() {
- existing := s.f.GetRegisteredResourceKey("res_with_values")
+func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithNonUniqueName_SameNamespace_Fails() {
+ // Create a resource in a namespace first
+ nsID := s.getNamespaceID("example.com")
+ name := "test_unique_ns_res"
req := ®isteredresources.CreateRegisteredResourceRequest{
- Name: existing.Name,
+ NamespaceId: nsID,
+ Name: name,
}
-
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, req)
+ s.Require().NoError(err)
+ s.NotNil(created)
+
+ // Try to create another with the same name in the same namespace
+ req2 := ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ }
+ dup, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, req2)
s.Require().Error(err)
s.Require().ErrorIs(err, db.ErrUniqueConstraintViolation)
- s.Nil(created)
+ s.Nil(dup)
}
// Get
@@ -252,7 +269,8 @@ func (s *RegisteredResourcesSuite) Test_ListRegisteredResources_OrdersByCreatedA
create := func(i int) string {
name := fmt.Sprintf("order-test-resource-%d-%d", i, suffix)
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: name,
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: name,
})
s.Require().NoError(err)
s.Require().NotNil(created)
@@ -275,7 +293,8 @@ func (s *RegisteredResourcesSuite) Test_ListRegisteredResources_OrdersByCreatedA
func (s *RegisteredResourcesSuite) Test_ListRegisteredResources_RegResValuesContainActionAttributeValues() {
// Create a registered resource with values that have action attribute values
newRegRes, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_list_reg_res_with_action_attr_values",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_list_reg_res_with_action_attr_values",
})
s.Require().NoError(err)
s.NotNil(newRegRes)
@@ -450,7 +469,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_Succeeds() {
}
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_update_res",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_update_res",
Metadata: &common.MetadataMutable{
Labels: labels,
},
@@ -508,7 +528,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_Succeeds() {
func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_NormalizedName_Succeeds() {
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_update_res_normalized",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_update_res_normalized",
})
s.Require().NoError(err)
s.NotNil(created)
@@ -540,17 +561,26 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_InvalidID_Fails
s.Nil(updated)
}
-func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_NonUniqueName_Fails() {
- created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_update_res_non_unique",
+func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_NonUniqueName_SameNamespace_Fails() {
+ nsID := s.getNamespaceID("example.com")
+ created1, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: "test_update_res_non_unique_a",
})
s.Require().NoError(err)
- s.NotNil(created)
+ s.NotNil(created1)
- existingRes := s.f.GetRegisteredResourceKey("res_only")
+ created2, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: "test_update_res_non_unique_b",
+ })
+ s.Require().NoError(err)
+ s.NotNil(created2)
+
+ // Try to rename created2 to created1's name in the same namespace
updated, err := s.db.PolicyClient.UpdateRegisteredResource(s.ctx, ®isteredresources.UpdateRegisteredResourceRequest{
- Id: created.GetId(),
- Name: existingRes.Name,
+ Id: created2.GetId(),
+ Name: created1.GetName(),
})
s.Require().Error(err)
s.Require().ErrorIs(err, db.ErrUniqueConstraintViolation)
@@ -561,7 +591,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResource_NonUniqueName_F
func (s *RegisteredResourcesSuite) Test_DeleteRegisteredResource_Succeeds() {
created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_delete_res",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_delete_res",
Values: []string{
"test_delete_value1",
"test_delete_value2",
@@ -620,7 +651,8 @@ func (s *RegisteredResourcesSuite) Test_DeleteRegisteredResource_WithInvalidID_F
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_Succeeds() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_value",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_value",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -637,7 +669,8 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_Succeeds()
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_NormalizedName_Succeeds() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_value_normalized",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_value_normalized",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -655,7 +688,8 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_Normalized
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_WithMetadata_Succeeds() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_value_metadata",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_value_metadata",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -679,7 +713,8 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_WithMetada
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_With_ActionAttributeValues_Succeeds() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_value_action_attr_values",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_value_action_attr_values",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -762,7 +797,8 @@ func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_WithNonUni
func (s *RegisteredResourcesSuite) Test_CreateRegisteredResourceValue_WithInvalidActionAttributeValues_Fails() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_create_res_value_invalid_action_attr_values",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_create_res_value_invalid_action_attr_values",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1046,7 +1082,8 @@ func (s *RegisteredResourcesSuite) Test_ListRegisteredResourceValues_NoPaginatio
func (s *RegisteredResourcesSuite) Test_ListRegisteredResourceValues_OrdersByCreatedAt_Succeeds() {
suffix := time.Now().UnixNano()
resource, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: fmt.Sprintf("order-test-res-%d", suffix),
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: fmt.Sprintf("order-test-res-%d", suffix),
})
s.Require().NoError(err)
s.Require().NotNil(resource)
@@ -1193,7 +1230,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResourceValue_Succeeds()
}
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_update_res_value",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_update_res_value",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1297,7 +1335,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResourceValue_Succeeds()
func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResourceValue_NormalizedName_Succeeds() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_update_res_value_normalized",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_update_res_value_normalized",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1338,7 +1377,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResourceValue_InvalidID_
func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResourceValue_NonUniqueResourceAndValue_Fails() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_update_res_value_non_unique",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_update_res_value_non_unique",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1371,7 +1411,8 @@ func (s *RegisteredResourcesSuite) Test_UpdateRegisteredResourceValue_NonUniqueR
func (s *RegisteredResourcesSuite) Test_DeleteRegisteredResourceValue_Succeeds() {
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_delete_res_value",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_delete_res_value",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1442,7 +1483,8 @@ func (s *RegisteredResourcesSuite) Test_DeleteAction_CascadeDeleteActionAttribut
s.Require().NoError(err)
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_delete_action_res",
+ NamespaceId: s.getNamespaceID("example.com"),
+ Name: "test_delete_action_res",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1507,7 +1549,8 @@ func (s *RegisteredResourcesSuite) Test_DeleteAttributeValue_CascadeDeleteAction
s.Require().NotNil(attrVal)
res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
- Name: "test_delete_attr_value_res",
+ NamespaceId: ns.GetId(),
+ Name: "test_delete_attr_value_res",
})
s.Require().NoError(err)
s.NotNil(res)
@@ -1549,3 +1592,358 @@ func (s *RegisteredResourcesSuite) Test_DeleteAttributeValue_CascadeDeleteAction
s.NotNil(resVal)
s.Empty(resVal.GetActionAttributeValues())
}
+
+///
+/// Namespace-scoped Registered Resources
+///
+
+func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_WithNamespaceFQN_Succeeds() {
+ nsFQN := s.getNamespaceFQN("example.com")
+ req := ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceFqn: nsFQN,
+ Name: "test_create_res_ns_fqn",
+ }
+
+ created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, req)
+ s.Require().NoError(err)
+ s.NotNil(created)
+ s.NotNil(created.GetNamespace())
+ s.Equal(s.getNamespaceID("example.com"), created.GetNamespace().GetId())
+ s.Equal("example.com", created.GetNamespace().GetName())
+ s.Equal(nsFQN, created.GetNamespace().GetFqn())
+}
+
+func (s *RegisteredResourcesSuite) Test_CreateRegisteredResource_SameNameDifferentNamespaces_Succeeds() {
+ name := "test_same_name_diff_ns"
+ nsID1 := s.getNamespaceID("example.com")
+ nsID2 := s.getNamespaceID("example.net")
+
+ created1, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID1,
+ Name: name,
+ })
+ s.Require().NoError(err)
+ s.NotNil(created1)
+ s.Equal(nsID1, created1.GetNamespace().GetId())
+
+ created2, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID2,
+ Name: name,
+ })
+ s.Require().NoError(err)
+ s.NotNil(created2)
+ s.Equal(nsID2, created2.GetNamespace().GetId())
+
+ // Both should exist with different IDs
+ s.NotEqual(created1.GetId(), created2.GetId())
+}
+
+func (s *RegisteredResourcesSuite) Test_GetRegisteredResource_ByNameWithNamespaceFQN_Succeeds() {
+ nsID := s.getNamespaceID("example.com")
+ nsFQN := s.getNamespaceFQN("example.com")
+ name := "test_get_by_name_ns"
+
+ created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ })
+ s.Require().NoError(err)
+ s.NotNil(created)
+
+ got, err := s.db.PolicyClient.GetRegisteredResource(s.ctx, ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Name{
+ Name: name,
+ },
+ NamespaceFqn: nsFQN,
+ })
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Equal(created.GetId(), got.GetId())
+ s.Equal(name, got.GetName())
+ s.NotNil(got.GetNamespace())
+ s.Equal(nsID, got.GetNamespace().GetId())
+}
+
+func (s *RegisteredResourcesSuite) Test_ListRegisteredResources_FilterByNamespaceID_Succeeds() {
+ nsID := s.getNamespaceID("example.net")
+ name := "test_list_ns_filter"
+
+ created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ })
+ s.Require().NoError(err)
+ s.NotNil(created)
+
+ list, err := s.db.PolicyClient.ListRegisteredResources(s.ctx, ®isteredresources.ListRegisteredResourcesRequest{
+ NamespaceId: nsID,
+ })
+ s.Require().NoError(err)
+ s.NotNil(list)
+
+ // Should find at least the one we just created
+ found := false
+ for _, r := range list.GetResources() {
+ s.Equal(nsID, r.GetNamespace().GetId(), "all listed resources should belong to the filtered namespace")
+ if r.GetId() == created.GetId() {
+ found = true
+ }
+ }
+ s.True(found, "created resource should be in the filtered list")
+}
+
+func (s *RegisteredResourcesSuite) Test_ListRegisteredResources_FilterByNamespaceFQN_Succeeds() {
+ nsID := s.getNamespaceID("example.net")
+ nsFQN := s.getNamespaceFQN("example.net")
+ name := "test_list_ns_fqn_filter"
+
+ created, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ })
+ s.Require().NoError(err)
+ s.NotNil(created)
+
+ list, err := s.db.PolicyClient.ListRegisteredResources(s.ctx, ®isteredresources.ListRegisteredResourcesRequest{
+ NamespaceFqn: nsFQN,
+ })
+ s.Require().NoError(err)
+ s.NotNil(list)
+
+ found := false
+ for _, r := range list.GetResources() {
+ s.Equal(nsID, r.GetNamespace().GetId(), "all listed resources should belong to the filtered namespace")
+ if r.GetId() == created.GetId() {
+ found = true
+ }
+ }
+ s.True(found, "created resource should be in the filtered list")
+}
+
+func (s *RegisteredResourcesSuite) Test_GetRegisteredResourceValue_NamespacedFQN_Succeeds() {
+ nsID := s.getNamespaceID("example.com")
+ name := "test_get_rrv_ns_fqn"
+ valueName := "test-value"
+
+ res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ Values: []string{valueName},
+ })
+ s.Require().NoError(err)
+ s.NotNil(res)
+
+ // Get by namespaced FQN
+ fqn := fmt.Sprintf("https://example.com/reg_res/%s/value/%s", name, valueName)
+ got, err := s.db.PolicyClient.GetRegisteredResourceValue(s.ctx, ®isteredresources.GetRegisteredResourceValueRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceValueRequest_Fqn{
+ Fqn: fqn,
+ },
+ })
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Equal(valueName, got.GetValue())
+ s.NotNil(got.GetResource())
+ s.NotNil(got.GetResource().GetNamespace())
+ s.Equal(nsID, got.GetResource().GetNamespace().GetId())
+}
+
+func (s *RegisteredResourcesSuite) Test_GetRegisteredResourceValuesByFQNs_NamespacedFormat_Succeeds() {
+ nsID := s.getNamespaceID("example.com")
+ name := "test_get_rrvs_ns_fqns"
+ val1 := "value1"
+ val2 := "value2"
+
+ res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ Values: []string{val1, val2},
+ })
+ s.Require().NoError(err)
+ s.NotNil(res)
+
+ fqn1 := fmt.Sprintf("https://example.com/reg_res/%s/value/%s", name, val1)
+ fqn2 := fmt.Sprintf("https://example.com/reg_res/%s/value/%s", name, val2)
+
+ fqnMap, err := s.db.PolicyClient.GetRegisteredResourceValuesByFQNs(s.ctx, ®isteredresources.GetRegisteredResourceValuesByFQNsRequest{
+ Fqns: []string{fqn1, fqn2},
+ })
+ s.Require().NoError(err)
+ s.Require().Len(fqnMap, 2)
+ s.NotNil(fqnMap[fqn1])
+ s.NotNil(fqnMap[fqn2])
+ s.Equal(val1, fqnMap[fqn1].GetValue())
+ s.Equal(val2, fqnMap[fqn2].GetValue())
+}
+
+func (s *RegisteredResourcesSuite) Test_RegisteredResource_NamespaceInResponses_Succeeds() {
+ nsID := s.getNamespaceID("example.com")
+ nsFQN := s.getNamespaceFQN("example.com")
+ name := "test_ns_in_responses"
+
+ res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: name,
+ Values: []string{"resp-val"},
+ })
+ s.Require().NoError(err)
+ s.NotNil(res)
+
+ // Verify namespace in Create response
+ s.NotNil(res.GetNamespace())
+ s.Equal(nsID, res.GetNamespace().GetId())
+ s.Equal("example.com", res.GetNamespace().GetName())
+ s.Equal(nsFQN, res.GetNamespace().GetFqn())
+
+ // Verify namespace in Get response
+ got, err := s.db.PolicyClient.GetRegisteredResource(s.ctx, ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Id{
+ Id: res.GetId(),
+ },
+ })
+ s.Require().NoError(err)
+ s.NotNil(got.GetNamespace())
+ s.Equal(nsID, got.GetNamespace().GetId())
+
+ // Verify namespace in List response
+ list, err := s.db.PolicyClient.ListRegisteredResources(s.ctx, ®isteredresources.ListRegisteredResourcesRequest{
+ NamespaceId: nsID,
+ })
+ s.Require().NoError(err)
+ found := false
+ for _, r := range list.GetResources() {
+ if r.GetId() == res.GetId() {
+ found = true
+ s.NotNil(r.GetNamespace())
+ s.Equal(nsID, r.GetNamespace().GetId())
+ }
+ }
+ s.True(found)
+
+ // Verify namespace in Value response
+ valResp, err := s.db.PolicyClient.GetRegisteredResourceValue(s.ctx, ®isteredresources.GetRegisteredResourceValueRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceValueRequest_Id{
+ Id: res.GetValues()[0].GetId(),
+ },
+ })
+ s.Require().NoError(err)
+ s.NotNil(valResp.GetResource())
+ s.NotNil(valResp.GetResource().GetNamespace())
+ s.Equal(nsID, valResp.GetResource().GetNamespace().GetId())
+}
+
+func (s *RegisteredResourcesSuite) Test_LegacyRegisteredResources_NoNamespace_StillAccessible() {
+ // Fixture resources are legacy (no namespace) - verify they're still accessible
+ existingRes := s.f.GetRegisteredResourceKey("res_only")
+
+ got, err := s.db.PolicyClient.GetRegisteredResource(s.ctx, ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Id{
+ Id: existingRes.ID,
+ },
+ })
+ s.Require().NoError(err)
+ s.NotNil(got)
+ s.Equal(existingRes.Name, got.GetName())
+ // Legacy resources have nil namespace
+ s.Nil(got.GetNamespace())
+}
+
+func (s *RegisteredResourcesSuite) Test_SameNamespaceEnforcement_DifferentNamespace_Fails() {
+ // Create a resource in example.com namespace
+ nsID := s.getNamespaceID("example.com")
+ res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: "test_same_ns_enforcement",
+ Values: []string{"enforce-val"},
+ })
+ s.Require().NoError(err)
+ s.NotNil(res)
+
+ // Create an attribute in example.net namespace
+ otherNsID := s.getNamespaceID("example.net")
+ attrName := fmt.Sprintf("test_enforce_attr_%d", time.Now().UnixNano())
+ attr, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.CreateAttributeRequest{
+ NamespaceId: otherNsID,
+ Name: attrName,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
+ Values: []string{"val1"},
+ })
+ s.Require().NoError(err)
+ s.NotNil(attr)
+ s.Require().NotEmpty(attr.GetValues())
+
+ crossNsAttrValID := attr.GetValues()[0].GetId()
+
+ // Try to create a value with action-attribute-value from different namespace -> should fail
+ _, err = s.db.PolicyClient.CreateRegisteredResourceValue(s.ctx, ®isteredresources.CreateRegisteredResourceValueRequest{
+ ResourceId: res.GetId(),
+ Value: "enforce-val2",
+ ActionAttributeValues: []*registeredresources.ActionAttributeValue{
+ {
+ ActionIdentifier: ®isteredresources.ActionAttributeValue_ActionName{
+ ActionName: actions.ActionNameRead,
+ },
+ AttributeValueIdentifier: ®isteredresources.ActionAttributeValue_AttributeValueId{
+ AttributeValueId: crossNsAttrValID,
+ },
+ },
+ },
+ })
+ s.Require().Error(err)
+ s.Require().ErrorIs(err, db.ErrForeignKeyViolation)
+}
+
+func (s *RegisteredResourcesSuite) Test_SameNamespaceEnforcement_SameNamespace_Succeeds() {
+ // Create a resource in example.com namespace
+ nsID := s.getNamespaceID("example.com")
+ res, err := s.db.PolicyClient.CreateRegisteredResource(s.ctx, ®isteredresources.CreateRegisteredResourceRequest{
+ NamespaceId: nsID,
+ Name: "test_same_ns_enforcement_ok",
+ Values: []string{"enforce-ok-val"},
+ })
+ s.Require().NoError(err)
+ s.NotNil(res)
+
+ // Create an attribute in the SAME namespace (example.com)
+ attrName := fmt.Sprintf("test_enforce_same_attr_%d", time.Now().UnixNano())
+ attr, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.CreateAttributeRequest{
+ NamespaceId: nsID,
+ Name: attrName,
+ Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
+ Values: []string{"val1"},
+ })
+ s.Require().NoError(err)
+ s.NotNil(attr)
+ s.Require().NotEmpty(attr.GetValues())
+
+ sameNsAttrValID := attr.GetValues()[0].GetId()
+
+ // Create a value with action-attribute-value from same namespace -> should succeed
+ resVal, err := s.db.PolicyClient.CreateRegisteredResourceValue(s.ctx, ®isteredresources.CreateRegisteredResourceValueRequest{
+ ResourceId: res.GetId(),
+ Value: "enforce-ok-val2",
+ ActionAttributeValues: []*registeredresources.ActionAttributeValue{
+ {
+ ActionIdentifier: ®isteredresources.ActionAttributeValue_ActionName{
+ ActionName: actions.ActionNameRead,
+ },
+ AttributeValueIdentifier: ®isteredresources.ActionAttributeValue_AttributeValueId{
+ AttributeValueId: sameNsAttrValID,
+ },
+ },
+ },
+ })
+ s.Require().NoError(err)
+ s.NotNil(resVal)
+ s.Require().Len(resVal.GetActionAttributeValues(), 1)
+}
+
+func (s *RegisteredResourcesSuite) getNamespaceID(key string) string {
+ ns := s.f.GetNamespaceKey(key)
+ return ns.ID
+}
+
+func (s *RegisteredResourcesSuite) getNamespaceFQN(key string) string {
+ ns := s.f.GetNamespaceKey(key)
+ return "https://" + ns.Name
+}
diff --git a/service/policy/db/attribute_values.sql.go b/service/policy/db/attribute_values.sql.go
index 97313ca62c..7582fed807 100644
--- a/service/policy/db/attribute_values.sql.go
+++ b/service/policy/db/attribute_values.sql.go
@@ -351,6 +351,44 @@ func (q *Queries) getAttributeValue(ctx context.Context, arg getAttributeValuePa
return i, err
}
+const getAttributeValueNamespaceIDs = `-- name: getAttributeValueNamespaceIDs :many
+SELECT av.id AS attribute_value_id, ad.namespace_id
+FROM attribute_values av
+JOIN attribute_definitions ad ON av.attribute_definition_id = ad.id
+WHERE av.id = ANY($1::uuid[])
+`
+
+type getAttributeValueNamespaceIDsRow struct {
+ AttributeValueID string `json:"attribute_value_id"`
+ NamespaceID string `json:"namespace_id"`
+}
+
+// getAttributeValueNamespaceIDs
+//
+// SELECT av.id AS attribute_value_id, ad.namespace_id
+// FROM attribute_values av
+// JOIN attribute_definitions ad ON av.attribute_definition_id = ad.id
+// WHERE av.id = ANY($1::uuid[])
+func (q *Queries) getAttributeValueNamespaceIDs(ctx context.Context, ids []string) ([]getAttributeValueNamespaceIDsRow, error) {
+ rows, err := q.db.Query(ctx, getAttributeValueNamespaceIDs, ids)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var items []getAttributeValueNamespaceIDsRow
+ for rows.Next() {
+ var i getAttributeValueNamespaceIDsRow
+ if err := rows.Scan(&i.AttributeValueID, &i.NamespaceID); err != nil {
+ return nil, err
+ }
+ items = append(items, i)
+ }
+ if err := rows.Err(); err != nil {
+ return nil, err
+ }
+ return items, nil
+}
+
const removeKeyAccessServerFromAttributeValue = `-- name: removeKeyAccessServerFromAttributeValue :execrows
DELETE FROM attribute_value_key_access_grants
WHERE attribute_value_id = $1 AND key_access_server_id = $2
diff --git a/service/policy/db/copyfrom.go b/service/policy/db/copyfrom.go
index 2f450ac823..07ec0ceaf7 100644
--- a/service/policy/db/copyfrom.go
+++ b/service/policy/db/copyfrom.go
@@ -39,9 +39,7 @@ func (r iteratorForcreateRegisteredResourceActionAttributeValues) Err() error {
return nil
}
-// --------------------------------------------------------------
-// Registered Resource Action Attribute Values
-// --------------------------------------------------------------
+// createRegisteredResourceActionAttributeValues
//
// INSERT INTO registered_resource_action_attribute_values (registered_resource_value_id, action_id, attribute_value_id)
// VALUES ($1, $2, $3)
diff --git a/service/policy/db/migrations/20260302000000_add_namespace_to_registered_resources.sql b/service/policy/db/migrations/20260302000000_add_namespace_to_registered_resources.sql
new file mode 100644
index 0000000000..adbcf44ee1
--- /dev/null
+++ b/service/policy/db/migrations/20260302000000_add_namespace_to_registered_resources.sql
@@ -0,0 +1,36 @@
+-- +goose Up
+-- +goose StatementBegin
+
+-- Add nullable namespace_id column to registered_resources
+ALTER TABLE registered_resources
+ ADD COLUMN namespace_id UUID REFERENCES attribute_namespaces(id) ON DELETE CASCADE;
+
+-- Drop existing global uniqueness constraint
+ALTER TABLE registered_resources DROP CONSTRAINT registered_resources_name_key;
+
+-- Namespaced RRs: unique name within namespace
+CREATE UNIQUE INDEX registered_resources_namespace_name_unique
+ ON registered_resources(namespace_id, name) WHERE namespace_id IS NOT NULL;
+
+-- Legacy RRs (no namespace): unique name globally
+CREATE UNIQUE INDEX registered_resources_name_unique
+ ON registered_resources(name) WHERE namespace_id IS NULL;
+
+-- Index for namespace-scoped queries
+CREATE INDEX idx_registered_resources_namespace
+ ON registered_resources(namespace_id);
+
+-- +goose StatementEnd
+
+-- +goose Down
+-- +goose StatementBegin
+
+DROP INDEX IF EXISTS idx_registered_resources_namespace;
+DROP INDEX IF EXISTS registered_resources_name_unique;
+DROP INDEX IF EXISTS registered_resources_namespace_name_unique;
+
+ALTER TABLE registered_resources ADD CONSTRAINT registered_resources_name_key UNIQUE (name);
+
+ALTER TABLE registered_resources DROP COLUMN IF EXISTS namespace_id;
+
+-- +goose StatementEnd
diff --git a/service/policy/db/models.go b/service/policy/db/models.go
index d3656a87a6..8e25e5b83e 100644
--- a/service/policy/db/models.go
+++ b/service/policy/db/models.go
@@ -346,7 +346,8 @@ type RegisteredResource struct {
// Timestamp when the record was created
CreatedAt pgtype.Timestamptz `json:"created_at"`
// Timestamp when the record was last updated
- UpdatedAt pgtype.Timestamptz `json:"updated_at"`
+ UpdatedAt pgtype.Timestamptz `json:"updated_at"`
+ NamespaceID pgtype.UUID `json:"namespace_id"`
}
// Table to store the linkage of registered resource values to actions and attribute values
diff --git a/service/policy/db/queries/attribute_values.sql b/service/policy/db/queries/attribute_values.sql
index 89941e0d05..ee11da1bf3 100644
--- a/service/policy/db/queries/attribute_values.sql
+++ b/service/policy/db/queries/attribute_values.sql
@@ -157,3 +157,9 @@ UPDATE attribute_value_public_key_map
SET key_access_server_key_id = sqlc.arg('new_key_id')::uuid
WHERE (key_access_server_key_id = sqlc.arg('old_key_id')::uuid)
RETURNING value_id;
+
+-- name: getAttributeValueNamespaceIDs :many
+SELECT av.id AS attribute_value_id, ad.namespace_id
+FROM attribute_values av
+JOIN attribute_definitions ad ON av.attribute_definition_id = ad.id
+WHERE av.id = ANY(sqlc.arg('ids')::uuid[]);
diff --git a/service/policy/db/queries/registered_resources.sql b/service/policy/db/queries/registered_resources.sql
index 3a626ad71a..17c9cacd2f 100644
--- a/service/policy/db/queries/registered_resources.sql
+++ b/service/policy/db/queries/registered_resources.sql
@@ -3,15 +3,47 @@
----------------------------------------------------------------
-- name: createRegisteredResource :one
-INSERT INTO registered_resources (name, metadata)
-VALUES ($1, $2)
-RETURNING id;
+WITH inserted AS (
+ INSERT INTO registered_resources (namespace_id, name, metadata)
+ SELECT
+ COALESCE(sqlc.narg('namespace_id')::uuid, fqns.namespace_id),
+ @name,
+ @metadata
+ FROM (
+ SELECT
+ sqlc.narg('namespace_id')::uuid as direct_namespace_id
+ ) direct
+ LEFT JOIN attribute_fqns fqns ON fqns.fqn = sqlc.narg('namespace_fqn')::text AND sqlc.narg('namespace_id')::text IS NULL
+ WHERE
+ (sqlc.narg('namespace_id')::text IS NOT NULL AND direct.direct_namespace_id IS NOT NULL) OR
+ (sqlc.narg('namespace_fqn')::text IS NOT NULL AND fqns.namespace_id IS NOT NULL)
+ RETURNING id, namespace_id, name, metadata
+)
+SELECT
+ i.id,
+ i.name,
+ i.metadata,
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', fqns.fqn
+ ) as namespace
+FROM inserted i
+JOIN attribute_namespaces n ON i.namespace_id = n.id
+LEFT JOIN attribute_fqns fqns ON fqns.namespace_id = n.id AND fqns.attribute_id IS NULL AND fqns.value_id IS NULL;
-- name: getRegisteredResource :one
SELECT
r.id,
r.name,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', r.metadata -> 'labels', 'created_at', r.created_at, 'updated_at', r.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
JSON_AGG(
JSON_BUILD_OBJECT(
'id', v.id,
@@ -19,21 +51,37 @@ SELECT
)
) FILTER (WHERE v.id IS NOT NULL) as values
FROM registered_resources r
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
LEFT JOIN registered_resource_values v ON v.registered_resource_id = r.id
WHERE
(sqlc.narg('id')::uuid IS NULL OR r.id = sqlc.narg('id')::uuid) AND
- (sqlc.narg('name')::text IS NULL OR r.name = sqlc.narg('name')::text)
-GROUP BY r.id;
+ (sqlc.narg('name')::text IS NULL OR r.name = sqlc.narg('name')::text) AND
+ (sqlc.narg('namespace_id')::uuid IS NULL OR r.namespace_id = sqlc.narg('namespace_id')::uuid) AND
+ (sqlc.narg('namespace_fqn')::text IS NULL OR ns_fqns.fqn = sqlc.narg('namespace_fqn')::text)
+GROUP BY r.id, n.id, ns_fqns.fqn;
-- name: listRegisteredResources :many
WITH counted AS (
- SELECT COUNT(id) AS total
- FROM registered_resources
+ SELECT COUNT(r.id) AS total
+ FROM registered_resources r
+ LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+ LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
+ WHERE
+ (sqlc.narg('namespace_id')::uuid IS NULL OR r.namespace_id = sqlc.narg('namespace_id')::uuid) AND
+ (sqlc.narg('namespace_fqn')::text IS NULL OR ns_fqns.fqn = sqlc.narg('namespace_fqn')::text)
)
SELECT
r.id,
r.name,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', r.metadata -> 'labels', 'created_at', r.created_at, 'updated_at', r.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
-- Aggregate all values for this resource into a JSON array, filtering NULL entries
JSON_AGG(
JSON_BUILD_OBJECT(
@@ -44,6 +92,8 @@ SELECT
) FILTER (WHERE v.id IS NOT NULL) as values,
counted.total
FROM registered_resources r
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
CROSS JOIN counted
LEFT JOIN registered_resource_values v ON v.registered_resource_id = r.id
-- Build a JSON array of action/attribute pairs for each resource value
@@ -69,9 +119,12 @@ LEFT JOIN LATERAL (
-- Correlate to the outer query's resource value
WHERE rav.registered_resource_value_id = v.id
) action_attrs ON true -- required syntax for LATERAL joins
-GROUP BY r.id, counted.total
+WHERE
+ (sqlc.narg('namespace_id')::uuid IS NULL OR r.namespace_id = sqlc.narg('namespace_id')::uuid) AND
+ (sqlc.narg('namespace_fqn')::text IS NULL OR ns_fqns.fqn = sqlc.narg('namespace_fqn')::text)
+GROUP BY r.id, n.id, ns_fqns.fqn, counted.total
ORDER BY r.created_at DESC
-LIMIT @limit_
+LIMIT @limit_
OFFSET @offset_;
-- name: updateRegisteredResource :execrows
@@ -100,6 +153,14 @@ SELECT
v.registered_resource_id,
v.value,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', v.metadata -> 'labels', 'created_at', v.created_at, 'updated_at', v.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
+ r.name as resource_name,
JSON_AGG(
JSON_BUILD_OBJECT(
'action', JSON_BUILD_OBJECT(
@@ -115,6 +176,8 @@ SELECT
) FILTER (WHERE rav.id IS NOT NULL) as action_attribute_values
FROM registered_resource_values v
JOIN registered_resources r ON v.registered_resource_id = r.id
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
LEFT JOIN registered_resource_action_attribute_values rav ON v.id = rav.registered_resource_value_id
LEFT JOIN actions a on rav.action_id = a.id
LEFT JOIN attribute_values av on rav.attribute_value_id = av.id
@@ -122,8 +185,9 @@ LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id
WHERE
(sqlc.narg('id')::uuid IS NULL OR v.id = sqlc.narg('id')::uuid) AND
(sqlc.narg('name')::text IS NULL OR r.name = sqlc.narg('name')::text) AND
- (sqlc.narg('value')::text IS NULL OR v.value = sqlc.narg('value')::text)
-GROUP BY v.id;
+ (sqlc.narg('value')::text IS NULL OR v.value = sqlc.narg('value')::text) AND
+ (sqlc.narg('namespace_fqn')::text IS NULL OR ns_fqns.fqn = sqlc.narg('namespace_fqn')::text)
+GROUP BY v.id, r.name, n.id, ns_fqns.fqn;
-- name: listRegisteredResourceValues :many
WITH counted AS (
@@ -136,6 +200,14 @@ SELECT
v.registered_resource_id,
v.value,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', v.metadata -> 'labels', 'created_at', v.created_at, 'updated_at', v.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
+ r.name as resource_name,
JSON_AGG(
JSON_BUILD_OBJECT(
'action', JSON_BUILD_OBJECT(
@@ -152,14 +224,16 @@ SELECT
counted.total
FROM registered_resource_values v
JOIN registered_resources r ON v.registered_resource_id = r.id
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
LEFT JOIN registered_resource_action_attribute_values rav ON v.id = rav.registered_resource_value_id
LEFT JOIN actions a on rav.action_id = a.id
LEFT JOIN attribute_values av on rav.attribute_value_id = av.id
-LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id
+LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id
CROSS JOIN counted
WHERE
sqlc.narg('registered_resource_id')::uuid IS NULL OR v.registered_resource_id = sqlc.narg('registered_resource_id')::uuid
-GROUP BY v.id, counted.total
+GROUP BY v.id, r.name, n.id, ns_fqns.fqn, counted.total
ORDER BY v.created_at DESC
LIMIT @limit_
OFFSET @offset_;
@@ -174,10 +248,16 @@ WHERE id = $1;
-- name: deleteRegisteredResourceValue :execrows
DELETE FROM registered_resource_values WHERE id = $1;
-----------------------------------------------------------------
+----------------------------------------------------------------
-- Registered Resource Action Attribute Values
----------------------------------------------------------------
+-- name: getRegisteredResourceNamespaceIDByValueID :one
+SELECT rr.namespace_id
+FROM registered_resources rr
+JOIN registered_resource_values rrv ON rrv.registered_resource_id = rr.id
+WHERE rrv.id = $1;
+
-- name: createRegisteredResourceActionAttributeValues :copyfrom
INSERT INTO registered_resource_action_attribute_values (registered_resource_value_id, action_id, attribute_value_id)
VALUES ($1, $2, $3);
diff --git a/service/policy/db/registered_resources.go b/service/policy/db/registered_resources.go
index 73bfe1e579..61d3109d54 100644
--- a/service/policy/db/registered_resources.go
+++ b/service/policy/db/registered_resources.go
@@ -57,28 +57,72 @@ func unmarshalRegisteredResourceActionAttributeValuesProto(actionAttrValuesJSON
return nil
}
+// hydrateNamespaceFromInterface converts a nullable namespace interface{} (from CASE WHEN SQL)
+// to a *policy.Namespace. Returns an empty Namespace if the namespace is NULL (legacy RRs without namespace).
+func hydrateNamespaceFromInterface(nsRaw interface{}) (*policy.Namespace, error) {
+ if nsRaw == nil {
+ return nil, nil //nolint:nilnil // nil namespace is valid for legacy RRs without namespace
+ }
+
+ var nsBytes []byte
+ switch v := nsRaw.(type) {
+ case []byte:
+ nsBytes = v
+ case map[string]interface{}:
+ var err error
+ nsBytes, err = json.Marshal(v)
+ if err != nil {
+ return nil, fmt.Errorf("failed to marshal namespace map: %w", err)
+ }
+ default:
+ return nil, fmt.Errorf("unexpected namespace type: %T", nsRaw)
+ }
+
+ ns := &policy.Namespace{}
+ if err := unmarshalNamespace(nsBytes, ns); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal registered resource namespace: %w", err)
+ }
+ return ns, nil
+}
+
///
/// Registered Resources
///
func (c PolicyDBClient) CreateRegisteredResource(ctx context.Context, r *registeredresources.CreateRegisteredResourceRequest) (*policy.RegisteredResource, error) {
name := strings.ToLower(r.GetName())
+ namespaceID := r.GetNamespaceId()
+ namespaceFqn := r.GetNamespaceFqn()
+
+ useID := len(namespaceID) > 0
+ parsedID := pgtypeUUID(namespaceID)
+ if useID && !parsedID.Valid {
+ return nil, db.ErrUUIDInvalid
+ }
+
metadataJSON, _, err := db.MarshalCreateMetadata(r.GetMetadata())
if err != nil {
return nil, err
}
- createdID, err := c.queries.createRegisteredResource(ctx, createRegisteredResourceParams{
- Name: name,
- Metadata: metadataJSON,
+ row, err := c.queries.createRegisteredResource(ctx, createRegisteredResourceParams{
+ NamespaceID: pgtypeUUID(namespaceID),
+ NamespaceFqn: pgtypeText(namespaceFqn),
+ Name: name,
+ Metadata: metadataJSON,
})
if err != nil {
return nil, db.WrapIfKnownInvalidQueryErr(err)
}
+ namespace := &policy.Namespace{}
+ if err := unmarshalNamespace(row.Namespace, namespace); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal registered resource namespace: %w", err)
+ }
+
for _, v := range r.GetValues() {
req := ®isteredresources.CreateRegisteredResourceValueRequest{
- ResourceId: createdID,
+ ResourceId: row.ID,
Value: v,
}
_, err := c.CreateRegisteredResourceValue(ctx, req)
@@ -89,7 +133,7 @@ func (c PolicyDBClient) CreateRegisteredResource(ctx context.Context, r *registe
return c.GetRegisteredResource(ctx, ®isteredresources.GetRegisteredResourceRequest{
Identifier: ®isteredresources.GetRegisteredResourceRequest_Id{
- Id: createdID,
+ Id: row.ID,
},
})
}
@@ -102,6 +146,16 @@ func (c PolicyDBClient) GetRegisteredResource(ctx context.Context, r *registered
params.ID = pgtypeUUID(r.GetId())
case r.GetName() != "":
params.Name = pgtypeText(strings.ToLower(r.GetName()))
+ namespaceID := r.GetNamespaceId()
+ if len(namespaceID) > 0 {
+ parsedID := pgtypeUUID(namespaceID)
+ if !parsedID.Valid {
+ return nil, db.ErrUUIDInvalid
+ }
+ params.NamespaceID = parsedID
+ } else if r.GetNamespaceFqn() != "" {
+ params.NamespaceFqn = pgtypeText(r.GetNamespaceFqn())
+ }
default:
return nil, db.ErrSelectIdentifierInvalid
}
@@ -116,20 +170,33 @@ func (c PolicyDBClient) GetRegisteredResource(ctx context.Context, r *registered
return nil, err
}
+ namespace, err := hydrateNamespaceFromInterface(rr.Namespace)
+ if err != nil {
+ return nil, err
+ }
+
values := []*policy.RegisteredResourceValue{}
if err = unmarshalRegisteredResourceValuesProto(rr.Values, &values); err != nil {
return nil, err
}
return &policy.RegisteredResource{
- Id: rr.ID,
- Name: rr.Name,
- Metadata: metadata,
- Values: values,
+ Id: rr.ID,
+ Name: rr.Name,
+ Metadata: metadata,
+ Namespace: namespace,
+ Values: values,
}, nil
}
func (c PolicyDBClient) ListRegisteredResources(ctx context.Context, r *registeredresources.ListRegisteredResourcesRequest) (*registeredresources.ListRegisteredResourcesResponse, error) {
+ namespaceID := r.GetNamespaceId()
+ useID := len(namespaceID) > 0
+ parsedID := pgtypeUUID(namespaceID)
+ if useID && !parsedID.Valid {
+ return nil, db.ErrUUIDInvalid
+ }
+
limit, offset := c.getRequestedLimitOffset(r.GetPagination())
maxLimit := c.listCfg.limitMax
@@ -138,8 +205,10 @@ func (c PolicyDBClient) ListRegisteredResources(ctx context.Context, r *register
}
list, err := c.queries.listRegisteredResources(ctx, listRegisteredResourcesParams{
- Limit: limit,
- Offset: offset,
+ NamespaceID: parsedID,
+ NamespaceFqn: pgtypeText(r.GetNamespaceFqn()),
+ Limit: limit,
+ Offset: offset,
})
if err != nil {
return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -153,16 +222,22 @@ func (c PolicyDBClient) ListRegisteredResources(ctx context.Context, r *register
return nil, err
}
+ namespace, err := hydrateNamespaceFromInterface(r.Namespace)
+ if err != nil {
+ return nil, err
+ }
+
values := []*policy.RegisteredResourceValue{}
if err = unmarshalRegisteredResourceValuesProto(r.Values, &values); err != nil {
return nil, err
}
rrList[i] = &policy.RegisteredResource{
- Id: r.ID,
- Name: r.Name,
- Metadata: metadata,
- Values: values,
+ Id: r.ID,
+ Name: r.Name,
+ Metadata: metadata,
+ Namespace: namespace,
+ Values: values,
}
}
@@ -281,6 +356,9 @@ func (c PolicyDBClient) GetRegisteredResourceValue(ctx context.Context, r *regis
}
params.Name = pgtypeText(parsed.Name)
params.Value = pgtypeText(parsed.Value)
+ if parsed.Namespace != "" {
+ params.NamespaceFqn = pgtypeText("https://" + parsed.Namespace)
+ }
default:
// unexpected type
return nil, db.ErrSelectIdentifierInvalid
@@ -296,6 +374,11 @@ func (c PolicyDBClient) GetRegisteredResourceValue(ctx context.Context, r *regis
return nil, err
}
+ namespace, err := hydrateNamespaceFromInterface(rv.Namespace)
+ if err != nil {
+ return nil, err
+ }
+
actionAttrValues := []*policy.RegisteredResourceValue_ActionAttributeValue{}
if err = unmarshalRegisteredResourceActionAttributeValuesProto(rv.ActionAttributeValues, &actionAttrValues); err != nil {
return nil, err
@@ -306,7 +389,9 @@ func (c PolicyDBClient) GetRegisteredResourceValue(ctx context.Context, r *regis
Value: rv.Value,
Metadata: metadata,
Resource: &policy.RegisteredResource{
- Id: rv.RegisteredResourceID,
+ Id: rv.RegisteredResourceID,
+ Name: rv.ResourceName,
+ Namespace: namespace,
},
ActionAttributeValues: actionAttrValues,
}, nil
@@ -371,6 +456,11 @@ func (c PolicyDBClient) ListRegisteredResourceValues(ctx context.Context, r *reg
return nil, err
}
+ namespace, err := hydrateNamespaceFromInterface(r.Namespace)
+ if err != nil {
+ return nil, err
+ }
+
actionAttrValues := []*policy.RegisteredResourceValue_ActionAttributeValue{}
if err = unmarshalRegisteredResourceActionAttributeValuesProto(r.ActionAttributeValues, &actionAttrValues); err != nil {
return nil, err
@@ -381,7 +471,9 @@ func (c PolicyDBClient) ListRegisteredResourceValues(ctx context.Context, r *reg
Value: r.Value,
Metadata: metadata,
Resource: &policy.RegisteredResource{
- Id: r.RegisteredResourceID,
+ Id: r.RegisteredResourceID,
+ Name: r.ResourceName,
+ Namespace: namespace,
},
ActionAttributeValues: actionAttrValues,
}
@@ -478,15 +570,22 @@ func (c PolicyDBClient) createRegisteredResourceActionAttributeValues(ctx contex
return nil
}
+ // Look up the namespace_id of the registered resource for same-namespace enforcement
+ nsUUID, err := c.queries.getRegisteredResourceNamespaceIDByValueID(ctx, registeredResourceValueID)
+ if err != nil {
+ return db.WrapIfKnownInvalidQueryErr(err)
+ }
+ resourceNamespaceID := UUIDToString(nsUUID)
+
createActionAttributeValueParams := make([]createRegisteredResourceActionAttributeValuesParams, len(actionAttrValues))
var actionID, attributeValueID string
for i, aav := range actionAttrValues {
- switch identifier := aav.GetActionIdentifier().(type) {
+ switch ident := aav.GetActionIdentifier().(type) {
case *registeredresources.ActionAttributeValue_ActionId:
- actionID = identifier.ActionId
+ actionID = ident.ActionId
case *registeredresources.ActionAttributeValue_ActionName:
a, err := c.queries.getAction(ctx, getActionParams{
- Name: pgtypeText(strings.ToLower(identifier.ActionName)),
+ Name: pgtypeText(strings.ToLower(ident.ActionName)),
})
if err != nil {
return db.WrapIfKnownInvalidQueryErr(err)
@@ -496,12 +595,12 @@ func (c PolicyDBClient) createRegisteredResourceActionAttributeValues(ctx contex
return db.ErrSelectIdentifierInvalid
}
- switch identifier := aav.GetAttributeValueIdentifier().(type) {
+ switch ident := aav.GetAttributeValueIdentifier().(type) {
case *registeredresources.ActionAttributeValue_AttributeValueId:
- attributeValueID = identifier.AttributeValueId
+ attributeValueID = ident.AttributeValueId
case *registeredresources.ActionAttributeValue_AttributeValueFqn:
av, err := c.queries.getAttributeValue(ctx, getAttributeValueParams{
- Fqn: pgtypeText(strings.ToLower(identifier.AttributeValueFqn)),
+ Fqn: pgtypeText(strings.ToLower(ident.AttributeValueFqn)),
})
if err != nil {
return db.WrapIfKnownInvalidQueryErr(err)
@@ -518,6 +617,24 @@ func (c PolicyDBClient) createRegisteredResourceActionAttributeValues(ctx contex
}
}
+ // Same-namespace enforcement (batch): all attribute values must belong to the same namespace as the registered resource
+ if resourceNamespaceID != "" {
+ avIDs := make([]string, len(createActionAttributeValueParams))
+ for i, p := range createActionAttributeValueParams {
+ avIDs[i] = p.AttributeValueID
+ }
+ rows, err := c.queries.getAttributeValueNamespaceIDs(ctx, avIDs)
+ if err != nil {
+ return db.WrapIfKnownInvalidQueryErr(err)
+ }
+ for _, row := range rows {
+ if row.NamespaceID != resourceNamespaceID {
+ return fmt.Errorf("attribute value %s belongs to namespace %s, but registered resource belongs to namespace %s: %w",
+ row.AttributeValueID, row.NamespaceID, resourceNamespaceID, db.ErrForeignKeyViolation)
+ }
+ }
+ }
+
count, err := c.queries.createRegisteredResourceActionAttributeValues(ctx, createActionAttributeValueParams)
if err != nil {
return db.WrapIfKnownInvalidQueryErr(err)
diff --git a/service/policy/db/registered_resources.sql.go b/service/policy/db/registered_resources.sql.go
index d3fee8aa61..000a36ae02 100644
--- a/service/policy/db/registered_resources.sql.go
+++ b/service/policy/db/registered_resources.sql.go
@@ -13,28 +13,97 @@ import (
const createRegisteredResource = `-- name: createRegisteredResource :one
-INSERT INTO registered_resources (name, metadata)
-VALUES ($1, $2)
-RETURNING id
+WITH inserted AS (
+ INSERT INTO registered_resources (namespace_id, name, metadata)
+ SELECT
+ COALESCE($1::uuid, fqns.namespace_id),
+ $2,
+ $3
+ FROM (
+ SELECT
+ $1::uuid as direct_namespace_id
+ ) direct
+ LEFT JOIN attribute_fqns fqns ON fqns.fqn = $4::text AND $1::text IS NULL
+ WHERE
+ ($1::text IS NOT NULL AND direct.direct_namespace_id IS NOT NULL) OR
+ ($4::text IS NOT NULL AND fqns.namespace_id IS NOT NULL)
+ RETURNING id, namespace_id, name, metadata
+)
+SELECT
+ i.id,
+ i.name,
+ i.metadata,
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', fqns.fqn
+ ) as namespace
+FROM inserted i
+JOIN attribute_namespaces n ON i.namespace_id = n.id
+LEFT JOIN attribute_fqns fqns ON fqns.namespace_id = n.id AND fqns.attribute_id IS NULL AND fqns.value_id IS NULL
`
type createRegisteredResourceParams struct {
- Name string `json:"name"`
- Metadata []byte `json:"metadata"`
+ NamespaceID pgtype.UUID `json:"namespace_id"`
+ Name string `json:"name"`
+ Metadata []byte `json:"metadata"`
+ NamespaceFqn pgtype.Text `json:"namespace_fqn"`
+}
+
+type createRegisteredResourceRow struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Metadata []byte `json:"metadata"`
+ Namespace []byte `json:"namespace"`
}
// --------------------------------------------------------------
// REGISTERED RESOURCES
// --------------------------------------------------------------
//
-// INSERT INTO registered_resources (name, metadata)
-// VALUES ($1, $2)
-// RETURNING id
-func (q *Queries) createRegisteredResource(ctx context.Context, arg createRegisteredResourceParams) (string, error) {
- row := q.db.QueryRow(ctx, createRegisteredResource, arg.Name, arg.Metadata)
- var id string
- err := row.Scan(&id)
- return id, err
+// WITH inserted AS (
+// INSERT INTO registered_resources (namespace_id, name, metadata)
+// SELECT
+// COALESCE($1::uuid, fqns.namespace_id),
+// $2,
+// $3
+// FROM (
+// SELECT
+// $1::uuid as direct_namespace_id
+// ) direct
+// LEFT JOIN attribute_fqns fqns ON fqns.fqn = $4::text AND $1::text IS NULL
+// WHERE
+// ($1::text IS NOT NULL AND direct.direct_namespace_id IS NOT NULL) OR
+// ($4::text IS NOT NULL AND fqns.namespace_id IS NOT NULL)
+// RETURNING id, namespace_id, name, metadata
+// )
+// SELECT
+// i.id,
+// i.name,
+// i.metadata,
+// JSON_BUILD_OBJECT(
+// 'id', n.id,
+// 'name', n.name,
+// 'fqn', fqns.fqn
+// ) as namespace
+// FROM inserted i
+// JOIN attribute_namespaces n ON i.namespace_id = n.id
+// LEFT JOIN attribute_fqns fqns ON fqns.namespace_id = n.id AND fqns.attribute_id IS NULL AND fqns.value_id IS NULL
+func (q *Queries) createRegisteredResource(ctx context.Context, arg createRegisteredResourceParams) (createRegisteredResourceRow, error) {
+ row := q.db.QueryRow(ctx, createRegisteredResource,
+ arg.NamespaceID,
+ arg.Name,
+ arg.Metadata,
+ arg.NamespaceFqn,
+ )
+ var i createRegisteredResourceRow
+ err := row.Scan(
+ &i.ID,
+ &i.Name,
+ &i.Metadata,
+ &i.Namespace,
+ )
+ return i, err
}
type createRegisteredResourceActionAttributeValuesParams struct {
@@ -122,6 +191,13 @@ SELECT
r.id,
r.name,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', r.metadata -> 'labels', 'created_at', r.created_at, 'updated_at', r.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
JSON_AGG(
JSON_BUILD_OBJECT(
'id', v.id,
@@ -129,23 +205,30 @@ SELECT
)
) FILTER (WHERE v.id IS NOT NULL) as values
FROM registered_resources r
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
LEFT JOIN registered_resource_values v ON v.registered_resource_id = r.id
WHERE
($1::uuid IS NULL OR r.id = $1::uuid) AND
- ($2::text IS NULL OR r.name = $2::text)
-GROUP BY r.id
+ ($2::text IS NULL OR r.name = $2::text) AND
+ ($3::uuid IS NULL OR r.namespace_id = $3::uuid) AND
+ ($4::text IS NULL OR ns_fqns.fqn = $4::text)
+GROUP BY r.id, n.id, ns_fqns.fqn
`
type getRegisteredResourceParams struct {
- ID pgtype.UUID `json:"id"`
- Name pgtype.Text `json:"name"`
+ ID pgtype.UUID `json:"id"`
+ Name pgtype.Text `json:"name"`
+ NamespaceID pgtype.UUID `json:"namespace_id"`
+ NamespaceFqn pgtype.Text `json:"namespace_fqn"`
}
type getRegisteredResourceRow struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Metadata []byte `json:"metadata"`
- Values []byte `json:"values"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Metadata []byte `json:"metadata"`
+ Namespace interface{} `json:"namespace"`
+ Values []byte `json:"values"`
}
// getRegisteredResource
@@ -154,6 +237,13 @@ type getRegisteredResourceRow struct {
// r.id,
// r.name,
// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', r.metadata -> 'labels', 'created_at', r.created_at, 'updated_at', r.updated_at)) as metadata,
+// CASE WHEN n.id IS NOT NULL THEN
+// JSON_BUILD_OBJECT(
+// 'id', n.id,
+// 'name', n.name,
+// 'fqn', ns_fqns.fqn
+// )
+// ELSE NULL END as namespace,
// JSON_AGG(
// JSON_BUILD_OBJECT(
// 'id', v.id,
@@ -161,29 +251,70 @@ type getRegisteredResourceRow struct {
// )
// ) FILTER (WHERE v.id IS NOT NULL) as values
// FROM registered_resources r
+// LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+// LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
// LEFT JOIN registered_resource_values v ON v.registered_resource_id = r.id
// WHERE
// ($1::uuid IS NULL OR r.id = $1::uuid) AND
-// ($2::text IS NULL OR r.name = $2::text)
-// GROUP BY r.id
+// ($2::text IS NULL OR r.name = $2::text) AND
+// ($3::uuid IS NULL OR r.namespace_id = $3::uuid) AND
+// ($4::text IS NULL OR ns_fqns.fqn = $4::text)
+// GROUP BY r.id, n.id, ns_fqns.fqn
func (q *Queries) getRegisteredResource(ctx context.Context, arg getRegisteredResourceParams) (getRegisteredResourceRow, error) {
- row := q.db.QueryRow(ctx, getRegisteredResource, arg.ID, arg.Name)
+ row := q.db.QueryRow(ctx, getRegisteredResource,
+ arg.ID,
+ arg.Name,
+ arg.NamespaceID,
+ arg.NamespaceFqn,
+ )
var i getRegisteredResourceRow
err := row.Scan(
&i.ID,
&i.Name,
&i.Metadata,
+ &i.Namespace,
&i.Values,
)
return i, err
}
+const getRegisteredResourceNamespaceIDByValueID = `-- name: getRegisteredResourceNamespaceIDByValueID :one
+
+SELECT rr.namespace_id
+FROM registered_resources rr
+JOIN registered_resource_values rrv ON rrv.registered_resource_id = rr.id
+WHERE rrv.id = $1
+`
+
+// --------------------------------------------------------------
+// Registered Resource Action Attribute Values
+// --------------------------------------------------------------
+//
+// SELECT rr.namespace_id
+// FROM registered_resources rr
+// JOIN registered_resource_values rrv ON rrv.registered_resource_id = rr.id
+// WHERE rrv.id = $1
+func (q *Queries) getRegisteredResourceNamespaceIDByValueID(ctx context.Context, id string) (pgtype.UUID, error) {
+ row := q.db.QueryRow(ctx, getRegisteredResourceNamespaceIDByValueID, id)
+ var namespace_id pgtype.UUID
+ err := row.Scan(&namespace_id)
+ return namespace_id, err
+}
+
const getRegisteredResourceValue = `-- name: getRegisteredResourceValue :one
SELECT
v.id,
v.registered_resource_id,
v.value,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', v.metadata -> 'labels', 'created_at', v.created_at, 'updated_at', v.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
+ r.name as resource_name,
JSON_AGG(
JSON_BUILD_OBJECT(
'action', JSON_BUILD_OBJECT(
@@ -199,6 +330,8 @@ SELECT
) FILTER (WHERE rav.id IS NOT NULL) as action_attribute_values
FROM registered_resource_values v
JOIN registered_resources r ON v.registered_resource_id = r.id
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
LEFT JOIN registered_resource_action_attribute_values rav ON v.id = rav.registered_resource_value_id
LEFT JOIN actions a on rav.action_id = a.id
LEFT JOIN attribute_values av on rav.attribute_value_id = av.id
@@ -206,22 +339,26 @@ LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id
WHERE
($1::uuid IS NULL OR v.id = $1::uuid) AND
($2::text IS NULL OR r.name = $2::text) AND
- ($3::text IS NULL OR v.value = $3::text)
-GROUP BY v.id
+ ($3::text IS NULL OR v.value = $3::text) AND
+ ($4::text IS NULL OR ns_fqns.fqn = $4::text)
+GROUP BY v.id, r.name, n.id, ns_fqns.fqn
`
type getRegisteredResourceValueParams struct {
- ID pgtype.UUID `json:"id"`
- Name pgtype.Text `json:"name"`
- Value pgtype.Text `json:"value"`
+ ID pgtype.UUID `json:"id"`
+ Name pgtype.Text `json:"name"`
+ Value pgtype.Text `json:"value"`
+ NamespaceFqn pgtype.Text `json:"namespace_fqn"`
}
type getRegisteredResourceValueRow struct {
- ID string `json:"id"`
- RegisteredResourceID string `json:"registered_resource_id"`
- Value string `json:"value"`
- Metadata []byte `json:"metadata"`
- ActionAttributeValues []byte `json:"action_attribute_values"`
+ ID string `json:"id"`
+ RegisteredResourceID string `json:"registered_resource_id"`
+ Value string `json:"value"`
+ Metadata []byte `json:"metadata"`
+ Namespace interface{} `json:"namespace"`
+ ResourceName string `json:"resource_name"`
+ ActionAttributeValues []byte `json:"action_attribute_values"`
}
// getRegisteredResourceValue
@@ -231,6 +368,14 @@ type getRegisteredResourceValueRow struct {
// v.registered_resource_id,
// v.value,
// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', v.metadata -> 'labels', 'created_at', v.created_at, 'updated_at', v.updated_at)) as metadata,
+// CASE WHEN n.id IS NOT NULL THEN
+// JSON_BUILD_OBJECT(
+// 'id', n.id,
+// 'name', n.name,
+// 'fqn', ns_fqns.fqn
+// )
+// ELSE NULL END as namespace,
+// r.name as resource_name,
// JSON_AGG(
// JSON_BUILD_OBJECT(
// 'action', JSON_BUILD_OBJECT(
@@ -246,6 +391,8 @@ type getRegisteredResourceValueRow struct {
// ) FILTER (WHERE rav.id IS NOT NULL) as action_attribute_values
// FROM registered_resource_values v
// JOIN registered_resources r ON v.registered_resource_id = r.id
+// LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+// LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
// LEFT JOIN registered_resource_action_attribute_values rav ON v.id = rav.registered_resource_value_id
// LEFT JOIN actions a on rav.action_id = a.id
// LEFT JOIN attribute_values av on rav.attribute_value_id = av.id
@@ -253,16 +400,24 @@ type getRegisteredResourceValueRow struct {
// WHERE
// ($1::uuid IS NULL OR v.id = $1::uuid) AND
// ($2::text IS NULL OR r.name = $2::text) AND
-// ($3::text IS NULL OR v.value = $3::text)
-// GROUP BY v.id
+// ($3::text IS NULL OR v.value = $3::text) AND
+// ($4::text IS NULL OR ns_fqns.fqn = $4::text)
+// GROUP BY v.id, r.name, n.id, ns_fqns.fqn
func (q *Queries) getRegisteredResourceValue(ctx context.Context, arg getRegisteredResourceValueParams) (getRegisteredResourceValueRow, error) {
- row := q.db.QueryRow(ctx, getRegisteredResourceValue, arg.ID, arg.Name, arg.Value)
+ row := q.db.QueryRow(ctx, getRegisteredResourceValue,
+ arg.ID,
+ arg.Name,
+ arg.Value,
+ arg.NamespaceFqn,
+ )
var i getRegisteredResourceValueRow
err := row.Scan(
&i.ID,
&i.RegisteredResourceID,
&i.Value,
&i.Metadata,
+ &i.Namespace,
+ &i.ResourceName,
&i.ActionAttributeValues,
)
return i, err
@@ -279,6 +434,14 @@ SELECT
v.registered_resource_id,
v.value,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', v.metadata -> 'labels', 'created_at', v.created_at, 'updated_at', v.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
+ r.name as resource_name,
JSON_AGG(
JSON_BUILD_OBJECT(
'action', JSON_BUILD_OBJECT(
@@ -295,14 +458,16 @@ SELECT
counted.total
FROM registered_resource_values v
JOIN registered_resources r ON v.registered_resource_id = r.id
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
LEFT JOIN registered_resource_action_attribute_values rav ON v.id = rav.registered_resource_value_id
LEFT JOIN actions a on rav.action_id = a.id
LEFT JOIN attribute_values av on rav.attribute_value_id = av.id
-LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id
+LEFT JOIN attribute_fqns fqns on av.id = fqns.value_id
CROSS JOIN counted
WHERE
$1::uuid IS NULL OR v.registered_resource_id = $1::uuid
-GROUP BY v.id, counted.total
+GROUP BY v.id, r.name, n.id, ns_fqns.fqn, counted.total
ORDER BY v.created_at DESC
LIMIT $3
OFFSET $2
@@ -315,12 +480,14 @@ type listRegisteredResourceValuesParams struct {
}
type listRegisteredResourceValuesRow struct {
- ID string `json:"id"`
- RegisteredResourceID string `json:"registered_resource_id"`
- Value string `json:"value"`
- Metadata []byte `json:"metadata"`
- ActionAttributeValues []byte `json:"action_attribute_values"`
- Total int64 `json:"total"`
+ ID string `json:"id"`
+ RegisteredResourceID string `json:"registered_resource_id"`
+ Value string `json:"value"`
+ Metadata []byte `json:"metadata"`
+ Namespace interface{} `json:"namespace"`
+ ResourceName string `json:"resource_name"`
+ ActionAttributeValues []byte `json:"action_attribute_values"`
+ Total int64 `json:"total"`
}
// listRegisteredResourceValues
@@ -335,6 +502,14 @@ type listRegisteredResourceValuesRow struct {
// v.registered_resource_id,
// v.value,
// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', v.metadata -> 'labels', 'created_at', v.created_at, 'updated_at', v.updated_at)) as metadata,
+// CASE WHEN n.id IS NOT NULL THEN
+// JSON_BUILD_OBJECT(
+// 'id', n.id,
+// 'name', n.name,
+// 'fqn', ns_fqns.fqn
+// )
+// ELSE NULL END as namespace,
+// r.name as resource_name,
// JSON_AGG(
// JSON_BUILD_OBJECT(
// 'action', JSON_BUILD_OBJECT(
@@ -351,6 +526,8 @@ type listRegisteredResourceValuesRow struct {
// counted.total
// FROM registered_resource_values v
// JOIN registered_resources r ON v.registered_resource_id = r.id
+// LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+// LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
// LEFT JOIN registered_resource_action_attribute_values rav ON v.id = rav.registered_resource_value_id
// LEFT JOIN actions a on rav.action_id = a.id
// LEFT JOIN attribute_values av on rav.attribute_value_id = av.id
@@ -358,7 +535,7 @@ type listRegisteredResourceValuesRow struct {
// CROSS JOIN counted
// WHERE
// $1::uuid IS NULL OR v.registered_resource_id = $1::uuid
-// GROUP BY v.id, counted.total
+// GROUP BY v.id, r.name, n.id, ns_fqns.fqn, counted.total
// ORDER BY v.created_at DESC
// LIMIT $3
// OFFSET $2
@@ -376,6 +553,8 @@ func (q *Queries) listRegisteredResourceValues(ctx context.Context, arg listRegi
&i.RegisteredResourceID,
&i.Value,
&i.Metadata,
+ &i.Namespace,
+ &i.ResourceName,
&i.ActionAttributeValues,
&i.Total,
); err != nil {
@@ -391,13 +570,25 @@ func (q *Queries) listRegisteredResourceValues(ctx context.Context, arg listRegi
const listRegisteredResources = `-- name: listRegisteredResources :many
WITH counted AS (
- SELECT COUNT(id) AS total
- FROM registered_resources
+ SELECT COUNT(r.id) AS total
+ FROM registered_resources r
+ LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+ LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
+ WHERE
+ ($1::uuid IS NULL OR r.namespace_id = $1::uuid) AND
+ ($2::text IS NULL OR ns_fqns.fqn = $2::text)
)
SELECT
r.id,
r.name,
JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', r.metadata -> 'labels', 'created_at', r.created_at, 'updated_at', r.updated_at)) as metadata,
+ CASE WHEN n.id IS NOT NULL THEN
+ JSON_BUILD_OBJECT(
+ 'id', n.id,
+ 'name', n.name,
+ 'fqn', ns_fqns.fqn
+ )
+ ELSE NULL END as namespace,
-- Aggregate all values for this resource into a JSON array, filtering NULL entries
JSON_AGG(
JSON_BUILD_OBJECT(
@@ -408,6 +599,8 @@ SELECT
) FILTER (WHERE v.id IS NOT NULL) as values,
counted.total
FROM registered_resources r
+LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
CROSS JOIN counted
LEFT JOIN registered_resource_values v ON v.registered_resource_id = r.id
LEFT JOIN LATERAL (
@@ -432,35 +625,53 @@ LEFT JOIN LATERAL (
-- Correlate to the outer query's resource value
WHERE rav.registered_resource_value_id = v.id
) action_attrs ON true -- required syntax for LATERAL joins
-GROUP BY r.id, counted.total
+WHERE
+ ($1::uuid IS NULL OR r.namespace_id = $1::uuid) AND
+ ($2::text IS NULL OR ns_fqns.fqn = $2::text)
+GROUP BY r.id, n.id, ns_fqns.fqn, counted.total
ORDER BY r.created_at DESC
-LIMIT $2
-OFFSET $1
+LIMIT $4
+OFFSET $3
`
type listRegisteredResourcesParams struct {
- Offset int32 `json:"offset_"`
- Limit int32 `json:"limit_"`
+ NamespaceID pgtype.UUID `json:"namespace_id"`
+ NamespaceFqn pgtype.Text `json:"namespace_fqn"`
+ Offset int32 `json:"offset_"`
+ Limit int32 `json:"limit_"`
}
type listRegisteredResourcesRow struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Metadata []byte `json:"metadata"`
- Values []byte `json:"values"`
- Total int64 `json:"total"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Metadata []byte `json:"metadata"`
+ Namespace interface{} `json:"namespace"`
+ Values []byte `json:"values"`
+ Total int64 `json:"total"`
}
// Build a JSON array of action/attribute pairs for each resource value
//
// WITH counted AS (
-// SELECT COUNT(id) AS total
-// FROM registered_resources
+// SELECT COUNT(r.id) AS total
+// FROM registered_resources r
+// LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+// LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
+// WHERE
+// ($1::uuid IS NULL OR r.namespace_id = $1::uuid) AND
+// ($2::text IS NULL OR ns_fqns.fqn = $2::text)
// )
// SELECT
// r.id,
// r.name,
// JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', r.metadata -> 'labels', 'created_at', r.created_at, 'updated_at', r.updated_at)) as metadata,
+// CASE WHEN n.id IS NOT NULL THEN
+// JSON_BUILD_OBJECT(
+// 'id', n.id,
+// 'name', n.name,
+// 'fqn', ns_fqns.fqn
+// )
+// ELSE NULL END as namespace,
// -- Aggregate all values for this resource into a JSON array, filtering NULL entries
// JSON_AGG(
// JSON_BUILD_OBJECT(
@@ -471,6 +682,8 @@ type listRegisteredResourcesRow struct {
// ) FILTER (WHERE v.id IS NOT NULL) as values,
// counted.total
// FROM registered_resources r
+// LEFT JOIN attribute_namespaces n ON r.namespace_id = n.id
+// LEFT JOIN attribute_fqns ns_fqns ON ns_fqns.namespace_id = n.id AND ns_fqns.attribute_id IS NULL AND ns_fqns.value_id IS NULL
// CROSS JOIN counted
// LEFT JOIN registered_resource_values v ON v.registered_resource_id = r.id
// LEFT JOIN LATERAL (
@@ -495,12 +708,20 @@ type listRegisteredResourcesRow struct {
// -- Correlate to the outer query's resource value
// WHERE rav.registered_resource_value_id = v.id
// ) action_attrs ON true -- required syntax for LATERAL joins
-// GROUP BY r.id, counted.total
+// WHERE
+// ($1::uuid IS NULL OR r.namespace_id = $1::uuid) AND
+// ($2::text IS NULL OR ns_fqns.fqn = $2::text)
+// GROUP BY r.id, n.id, ns_fqns.fqn, counted.total
// ORDER BY r.created_at DESC
-// LIMIT $2
-// OFFSET $1
+// LIMIT $4
+// OFFSET $3
func (q *Queries) listRegisteredResources(ctx context.Context, arg listRegisteredResourcesParams) ([]listRegisteredResourcesRow, error) {
- rows, err := q.db.Query(ctx, listRegisteredResources, arg.Offset, arg.Limit)
+ rows, err := q.db.Query(ctx, listRegisteredResources,
+ arg.NamespaceID,
+ arg.NamespaceFqn,
+ arg.Offset,
+ arg.Limit,
+ )
if err != nil {
return nil, err
}
@@ -512,6 +733,7 @@ func (q *Queries) listRegisteredResources(ctx context.Context, arg listRegistere
&i.ID,
&i.Name,
&i.Metadata,
+ &i.Namespace,
&i.Values,
&i.Total,
); err != nil {
diff --git a/service/policy/registeredresources/registered_resources.proto b/service/policy/registeredresources/registered_resources.proto
index 6f46aecc7d..85fd52d673 100644
--- a/service/policy/registeredresources/registered_resources.proto
+++ b/service/policy/registeredresources/registered_resources.proto
@@ -79,13 +79,14 @@ message GetRegisteredResourceRequest {
}
// Optional - namespace context for name-based lookups (since names are not globally unique for namespaced RRs)
+ option (buf.validate.message).oneof = { fields: ["namespace_id", "namespace_fqn"], required: false };
string namespace_fqn = 3 [
- (buf.validate.field).cel = {
- id: "optional_namespace_fqn",
- message: "Namespace FQN must be a valid URI if provided",
- expression: "size(this) == 0 || this.isUri()"
+ (buf.validate.field).string = {
+ min_len : 1
+ uri : true
}
];
+ string namespace_id = 4 [(buf.validate.field).string.uuid = true];
}
message GetRegisteredResourceResponse {
policy.RegisteredResource resource = 1;
diff --git a/service/policy/registeredresources/registered_resources_test.go b/service/policy/registeredresources/registered_resources_test.go
index e527a347f5..06dcfaf84e 100644
--- a/service/policy/registeredresources/registered_resources_test.go
+++ b/service/policy/registeredresources/registered_resources_test.go
@@ -241,6 +241,24 @@ func (s *RegisteredResourcesSuite) TestGetRegisteredResource_Valid_Succeeds() {
},
},
},
+ {
+ name: "Name with Namespace ID",
+ req: ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Name{
+ Name: validName,
+ },
+ NamespaceId: validUUID,
+ },
+ },
+ {
+ name: "Name with Namespace FQN",
+ req: ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Name{
+ Name: validName,
+ },
+ NamespaceFqn: validURI,
+ },
+ },
}
for _, tc := range testCases {
@@ -281,6 +299,37 @@ func (s *RegisteredResourcesSuite) TestGetRegisteredResource_Invalid_Fails() {
},
errMsg: errMsgNameFormat,
},
+ {
+ name: "Invalid Namespace ID (non-UUID)",
+ req: ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Name{
+ Name: validName,
+ },
+ NamespaceId: invalidUUID,
+ },
+ errMsg: errMsgUUID,
+ },
+ {
+ name: "Invalid Namespace FQN (non-URI)",
+ req: ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Name{
+ Name: validName,
+ },
+ NamespaceFqn: invalidURI,
+ },
+ errMsg: errMsgURI,
+ },
+ {
+ name: "Both Namespace ID and FQN provided (oneof violation)",
+ req: ®isteredresources.GetRegisteredResourceRequest{
+ Identifier: ®isteredresources.GetRegisteredResourceRequest_Name{
+ Name: validName,
+ },
+ NamespaceId: validUUID,
+ NamespaceFqn: validURI,
+ },
+ errMsg: "oneof",
+ },
}
for _, tc := range testCases {