From 53f5e85446e51247c228370288132356081bd390 Mon Sep 17 00:00:00 2001 From: Krish Suchak Date: Mon, 11 Mar 2024 16:03:54 -0400 Subject: [PATCH 01/31] more merge conflicts --- cmd/migrate.go | 1 - docs/grpc/index.html | 2 +- .../policy/attributes/attributes.swagger.json | 3 +- .../resource_mapping.swagger.json | 3 +- .../subject_mapping.swagger.json | 3 +- integration/attribute_fqns_test.go.x | 227 ++++ integration/resource_mappings_test.go.x | 276 +++++ internal/db/db.go | 1 - internal/fixtures/fixtures.go | 33 + internal/fixtures/policy_fixtures.yaml | 24 +- internal/set/set.go | 103 ++ .../20240223000000_create_val_members.md | 29 + .../20240223000000_create_val_members.sql | 121 +++ .../go/policy/attributes/attributes.pb.go | 968 +++++++++--------- .../policy/attributes/AttributesProto.java | 351 +++---- .../platform/policy/attributes/Value.java | 434 +++++--- .../policy/attributes/ValueOrBuilder.java | 31 +- services/policy/attributes/attributes.proto | 2 +- services/policy/db/attribute_values.go | 346 ++++++- services/policy/db/attributes.go | 87 +- services/policy/db/policy.go | 3 + services/policy/db/resource_mapping.go | 12 +- 22 files changed, 2209 insertions(+), 851 deletions(-) create mode 100644 integration/attribute_fqns_test.go.x create mode 100644 integration/resource_mappings_test.go.x create mode 100644 internal/set/set.go create mode 100644 migrations/20240223000000_create_val_members.md create mode 100644 migrations/20240223000000_create_val_members.sql diff --git a/cmd/migrate.go b/cmd/migrate.go index 45dd4dfce6..7e3e087191 100644 --- a/cmd/migrate.go +++ b/cmd/migrate.go @@ -31,7 +31,6 @@ var ( fmt.Print("migration down applied successfully") }, } - migrateUpCmd = &cobra.Command{ Use: "up", Short: "Run database migrations up to the latest version", diff --git a/docs/grpc/index.html b/docs/grpc/index.html index 5137277121..787a9c466a 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -3831,7 +3831,7 @@

Value

members - string + Value repeated

list of attribute values that this value is related to (attribute group)

diff --git a/docs/openapi/policy/attributes/attributes.swagger.json b/docs/openapi/policy/attributes/attributes.swagger.json index 8b5d369db6..322759e31e 100644 --- a/docs/openapi/policy/attributes/attributes.swagger.json +++ b/docs/openapi/policy/attributes/attributes.swagger.json @@ -851,7 +851,8 @@ "members": { "type": "array", "items": { - "type": "string" + "type": "object", + "$ref": "#/definitions/policyattributesValue" }, "title": "list of attribute values that this value is related to (attribute group)" }, diff --git a/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json b/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json index 82787100e5..17c93e8b46 100644 --- a/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json +++ b/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json @@ -367,7 +367,8 @@ "members": { "type": "array", "items": { - "type": "string" + "type": "object", + "$ref": "#/definitions/policyattributesValue" }, "title": "list of attribute values that this value is related to (attribute group)" }, diff --git a/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json b/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json index 615c544995..81b195d278 100644 --- a/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json +++ b/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json @@ -582,7 +582,8 @@ "members": { "type": "array", "items": { - "type": "string" + "type": "object", + "$ref": "#/definitions/policyattributesValue" }, "title": "list of attribute values that this value is related to (attribute group)" }, diff --git a/integration/attribute_fqns_test.go.x b/integration/attribute_fqns_test.go.x new file mode 100644 index 0000000000..8ab635abe0 --- /dev/null +++ b/integration/attribute_fqns_test.go.x @@ -0,0 +1,227 @@ +package integration + +import ( + "context" + "fmt" + "log/slog" + "testing" + + "github.com/opentdf/platform/internal/db" + "github.com/opentdf/platform/internal/fixtures" + "github.com/opentdf/platform/protocol/go/policy/attributes" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type AttributeFqnSuite struct { + suite.Suite + schema string + f fixtures.Fixtures + db fixtures.DBInterface + ctx context.Context +} + +func fqnBuilder(n string, a string, v string) string { + fqn := "https://" + if n != "" && a != "" && v != "" { + return fqn + n + "/attr/" + a + "/value/" + v + } else if n != "" && a != "" && v == "" { + return fqn + n + "/attr/" + a + } else if n != "" && a == "" { + return fqn + n + } else { + panic("Invalid FQN") + } +} + +func TestAttributeFqnSuite(t *testing.T) { + if testing.Short() { + t.Skip("skipping attributes integration tests") + } + suite.Run(t, new(AttributeFqnSuite)) +} + +func (s *AttributeFqnSuite) SetupSuite() { + slog.Info("setting up db.AttributeFqn test suite") + s.ctx = context.Background() + s.schema = "test_opentdf_attribute_fqn" + s.db = fixtures.NewDBInterface(*Config) + s.f = fixtures.NewFixture(s.db) + s.f.Provision() +} + +func (s *AttributeFqnSuite) TearDownSuite() { + slog.Info("tearing down db.AttributeFqn test suite") + s.f.TearDown() +} + +// Test Create Namespace +func (s *AttributeFqnSuite) TestCreateNamespace() { + name := "test_namespace" + id, err := s.db.PolicyClient.CreateNamespace(s.ctx, name) + s.NoError(err) + // Verify FQN + fqn, err := s.db.PolicyClient.GetNamespace(s.ctx, id) + s.NoError(err) + s.NotEmpty(fqn.Fqn) + s.Equal(fqnBuilder(name, "", ""), fqn.Fqn) +} + +// Test Create Attribute +func (s *AttributeFqnSuite) TestCreateAttribute() { + n := s.f.GetNamespaceKey("example.com") + name := "test_namespace" + a, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.AttributeCreateUpdate{ + NamespaceId: n.Id, + Name: name, + Rule: attributes.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF, + }) + s.NoError(err) + // Verify FQN + fqn, err := s.db.PolicyClient.GetAttribute(s.ctx, a.Id) + s.NoError(err) + s.NotEmpty(fqn.Fqn) + s.Equal(fqnBuilder(n.Name, a.Name, ""), fqn.Fqn) +} + +// Test Create Attribute Value +func (s *AttributeFqnSuite) TestCreateAttributeValue() { + a := s.f.GetAttributeKey("example.com/attr/attr1") + n := s.f.GetNamespaceKey("example.com") + name := "test_namespace" + v, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, a.Id, &attributes.ValueCreateUpdate{ + Value: name, + }) + s.NoError(err) + // Verify FQN + fqn, err := s.db.PolicyClient.GetAttributeValue(s.ctx, v.Id) + s.NoError(err) + s.NotEmpty(fqn.Fqn) + s.Equal(fqnBuilder(n.Name, a.Name, v.Value), fqn.Fqn) +} + +// Test Get one attribute by the FQN of one of its values +func (s *AttributeFqnSuite) TestGetAttributeByFqn_WithAttrValueFqn() { + fqnFixtureKey := "example.com/attr/attr1/value/value1" + fullFqn := fmt.Sprintf("https://%s", fqnFixtureKey) + valueFixture := s.f.GetAttributeValueKey(fqnFixtureKey) + + attr, err := s.db.PolicyClient.GetAttributeByFqn(s.ctx, fullFqn) + s.NoError(err) + + // there should be only one value + s.Equal(1, len(attr.Values)) + + // the value should match the fixture + av := attr.Values[0] + s.Equal(attr.Id, valueFixture.AttributeDefinitionId) + s.Equal(av.Id, valueFixture.Id) + s.Equal(av.Value, valueFixture.Value) +} + +// Test Get one attribute by the FQN of the attribute definition +func (s *AttributeFqnSuite) TestGetAttributeByFqn_WithAttrFqn() { + fqnFixtureKey := "example.net/attr/attr1" + fullFqn := fmt.Sprintf("https://%s", fqnFixtureKey) + attrFixture := s.f.GetAttributeKey(fqnFixtureKey) + + attr, err := s.db.PolicyClient.GetAttributeByFqn(s.ctx, fullFqn) + s.NoError(err) + + // the number of values should match the fixture + s.Equal(2, len(attr.Values)) + + // the attribute should match the fixture + s.Equal(attr.Id, attrFixture.Id) + s.Equal(attr.Name, attrFixture.Name) + s.Equal(attr.Rule.String(), fmt.Sprintf("ATTRIBUTE_RULE_TYPE_ENUM_%s", attrFixture.Rule)) + s.Equal(attr.Active.Value, attrFixture.Active) +} + +// Test multiple get attributes by multiple fqns +func (s *AttributeFqnSuite) TestGetAttributesByValueFqns() { + namespace := "testing_multiple_fqns.get" + attr := "test_attr" + value1 := "test_value" + value2 := "test_value_2" + fqn1 := fqnBuilder(namespace, attr, value1) + fqn2 := fqnBuilder(namespace, attr, value2) + + // Create namespace + nsId, err := s.db.PolicyClient.CreateNamespace(s.ctx, namespace) + assert.NoError(s.T(), err) + + // Create attribute + a, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.AttributeCreateUpdate{ + NamespaceId: nsId, + Name: attr, + Rule: attributes.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF, + }) + assert.NoError(s.T(), err) + + // Create attribute value1 + v1, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, a.Id, &attributes.ValueCreateUpdate{ + Value: value1, + }) + assert.NoError(s.T(), err) + + // Get attributes by fqns with a solo value + fqns := []string{fqn1} + attributeAndValue, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, fqns) + assert.NoError(s.T(), err) + + // Verify attribute1 is sole attribute + assert.Len(s.T(), attributeAndValue, 1) + val, ok := attributeAndValue[fqn1] + assert.True(s.T(), ok) + assert.Equal(s.T(), a.Id, val.Attribute.Id) + + assert.Equal(s.T(), v1.Id, val.Attribute.Values[0].Id) + assert.Equal(s.T(), v1.Value, val.Value.Value) + + assert.Equal(s.T(), v1.Value, val.Attribute.Values[0].Value) + assert.Equal(s.T(), v1.Id, val.Value.Id) + + // Create attribute value2 + v2, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, a.Id, &attributes.ValueCreateUpdate{ + Value: value2, + }) + assert.NoError(s.T(), err) + + // Get attributes by fqns with two values + fqns = []string{fqn1, fqn2} + attributeAndValue, err = s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, fqns) + assert.NoError(s.T(), err) + assert.Len(s.T(), attributeAndValue, 2) + + val, ok = attributeAndValue[fqn2] + assert.True(s.T(), ok) + assert.Equal(s.T(), a.Id, val.Attribute.Id) + + for _, v := range val.Attribute.Values { + if v.Id == v1.Id { + assert.Equal(s.T(), v1.Id, v.Id) + assert.Equal(s.T(), v1.Value, v.Value) + } else if v.Id == v2.Id { + assert.Equal(s.T(), v2.Id, v.Id) + assert.Equal(s.T(), v2.Value, v.Value) + } else { + assert.Fail(s.T(), "unexpected value", v) + } + } +} + +func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithNonValueFqns() { + nsFqn := fqnBuilder("example.com", "", "") + attrFqn := fqnBuilder("example.com", "attr1", "") + v, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, []string{nsFqn}) + assert.Error(s.T(), err) + assert.Nil(s.T(), v) + assert.ErrorIs(s.T(), err, db.ErrFqnMissingValue) + + v, err = s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, []string{attrFqn}) + assert.Error(s.T(), err) + assert.Nil(s.T(), v) + assert.ErrorIs(s.T(), err, db.ErrFqnMissingValue) +} diff --git a/integration/resource_mappings_test.go.x b/integration/resource_mappings_test.go.x new file mode 100644 index 0000000000..ab5705391f --- /dev/null +++ b/integration/resource_mappings_test.go.x @@ -0,0 +1,276 @@ +package integration + +import ( + "context" + "fmt" + "log/slog" + "testing" + + "github.com/opentdf/platform/internal/db" + "github.com/opentdf/platform/internal/fixtures" + "github.com/opentdf/platform/protocol/go/common" + resourcemapping "github.com/opentdf/platform/protocol/go/policy/resourcemapping" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +var nonExistentResourceMappingUUID = "45674556-8888-9999-9999-000001230000" + +type ResourceMappingsSuite struct { + suite.Suite + schema string + f fixtures.Fixtures + db fixtures.DBInterface + ctx context.Context +} + +func (s *ResourceMappingsSuite) SetupSuite() { + slog.Info("setting up db.ResourceMappings test suite") + s.ctx = context.Background() + s.schema = "test_opentdf_resource_mappings" + s.db = fixtures.NewDBInterface(*Config) + s.f = fixtures.NewFixture(s.db) + s.f.Provision() +} + +func (s *ResourceMappingsSuite) TearDownSuite() { + slog.Info("tearing down db.ResourceMappings test suite") + s.f.TearDown() +} + +func (s *ResourceMappingsSuite) getResourceMappingFixtures() []fixtures.FixtureDataResourceMapping { + return []fixtures.FixtureDataResourceMapping{ + s.f.GetResourceMappingKey("resource_mapping_to_attribute_value1"), + s.f.GetResourceMappingKey("resource_mapping_to_attribute_value2"), + s.f.GetResourceMappingKey("resource_mapping_to_attribute_value3"), + } +} + +func (s *ResourceMappingsSuite) Test_CreateResourceMapping() { + metadata := &common.MetadataMutable{ + Labels: map[string]string{ + "name": "this is the test name of my resource mapping", + }, + Description: "test create resource mapping description", + } + + attrValue := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Metadata: metadata, + Terms: []string{"term1", "term2"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) +} + +func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithUnknownAttributeValueFails() { + metadata := &common.MetadataMutable{} + + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: nonExistentAttributeValueUuid, + Metadata: metadata, + Terms: []string{"term1", "term2"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.NotNil(s.T(), err) + assert.Nil(s.T(), createdMapping) + assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation) +} + +func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithEmptyTermsSucceeds() { + metadata := &common.MetadataMutable{} + + attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Metadata: metadata, + Terms: []string{}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) + assert.NotNil(s.T(), createdMapping.Terms) + assert.Equal(s.T(), len(createdMapping.Terms), 0) +} + +func (s *ResourceMappingsSuite) Test_ListResourceMappings() { + // make sure we can get all fixtures + testData := s.getResourceMappingFixtures() + mappings, err := s.db.PolicyClient.ListResourceMappings(s.ctx) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), mappings) + for _, testMapping := range testData { + found := false + for _, mapping := range mappings { + if testMapping.Id == mapping.Id { + found = true + break + } + } + assert.True(s.T(), found, fmt.Sprintf("expected to find mapping %s", testMapping.Id)) + } +} + +func (s *ResourceMappingsSuite) Test_GetResourceMapping() { + // make sure we can get all fixtures + testData := s.getResourceMappingFixtures() + for _, testMapping := range testData { + mapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, testMapping.Id) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), mapping) + assert.Equal(s.T(), testMapping.Id, mapping.Id) + assert.Equal(s.T(), testMapping.AttributeValueId, mapping.AttributeValue.Id) + assert.Equal(s.T(), testMapping.Terms, mapping.Terms) + } +} + +func (s *ResourceMappingsSuite) Test_GetResourceMappingWithUnknownIdFails() { + mapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, nonExistentResourceMappingUUID) + assert.NotNil(s.T(), err) + assert.Nil(s.T(), mapping) + assert.ErrorIs(s.T(), err, db.ErrNotFound) +} + +func (s *ResourceMappingsSuite) Test_GetResourceMappingOfCreatedSucceeds() { + metadata := &common.MetadataMutable{} + + attrValue := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value2") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Metadata: metadata, + Terms: []string{"term1", "term2"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) + + got, err := s.db.PolicyClient.GetResourceMapping(s.ctx, createdMapping.Id) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), mapping) + assert.Equal(s.T(), createdMapping.Id, got.Id) + assert.Equal(s.T(), createdMapping.AttributeValue.Id, got.AttributeValue.Id) + assert.Equal(s.T(), createdMapping.Terms, mapping.Terms) +} + +func (s *ResourceMappingsSuite) Test_UpdateResourceMapping() { + metadata := &common.MetadataMutable{ + Labels: map[string]string{ + "name": "some test resource mapping name", + }, + Description: "some description", + } + + attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Metadata: metadata, + Terms: []string{"some term", "other term"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) + + updatedMetadata := &common.MetadataMutable{ + Labels: map[string]string{ + "name": "new name", + }, + Description: "new description", + } + + // update the created with new metadata and terms + updatedMapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: createdMapping.AttributeValue.Id, + Metadata: updatedMetadata, + Terms: []string{"updated term1", "updated term 2"}, + } + updated, err := s.db.PolicyClient.UpdateResourceMapping(s.ctx, createdMapping.Id, updatedMapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), updated) + + // get after update to verify db reflects changes made + got, err := s.db.PolicyClient.GetResourceMapping(s.ctx, createdMapping.Id) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), got) + assert.Equal(s.T(), createdMapping.Id, got.Id) + assert.Equal(s.T(), createdMapping.AttributeValue.Id, got.AttributeValue.Id) + assert.Equal(s.T(), updatedMapping.Terms, got.Terms) + assert.Equal(s.T(), updatedMetadata.Description, got.Metadata.Description) + assert.EqualValues(s.T(), updatedMetadata.Labels, got.Metadata.Labels) +} + +func (s *ResourceMappingsSuite) Test_UpdateResourceMappingWithUnknownIdFails() { + attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Terms: []string{"asdf qwerty"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) + + // update the created with new metadata and terms + updatedMapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: createdMapping.AttributeValue.Id, + Terms: []string{"asdf updated term1"}, + } + updated, err := s.db.PolicyClient.UpdateResourceMapping(s.ctx, nonExistentResourceMappingUUID, updatedMapping) + assert.NotNil(s.T(), err) + assert.Nil(s.T(), updated) + assert.ErrorIs(s.T(), err, db.ErrNotFound) +} + +func (s *ResourceMappingsSuite) Test_UpdateResourceMappingWithUnknownAttributeValueIdFails() { + attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Terms: []string{"testing"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) + + // update the created with new metadata and terms + updatedMapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: nonExistentAttributeValueUuid, + Terms: []string{"testing-2"}, + } + updated, err := s.db.PolicyClient.UpdateResourceMapping(s.ctx, createdMapping.Id, updatedMapping) + assert.NotNil(s.T(), err) + assert.Nil(s.T(), updated) + assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation) +} + +func (s *ResourceMappingsSuite) Test_DeleteResourceMapping() { + attrValue := s.f.GetAttributeValueKey("example.net/attr/attr1/value/value1") + mapping := &resourcemapping.ResourceMappingCreateUpdate{ + AttributeValueId: attrValue.Id, + Terms: []string{"term1", "term2"}, + } + createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), createdMapping) + + deleted, err := s.db.PolicyClient.DeleteResourceMapping(s.ctx, createdMapping.Id) + assert.Nil(s.T(), err) + assert.NotNil(s.T(), deleted) + + deletedMapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, createdMapping.Id) + assert.NotNil(s.T(), err) + assert.Nil(s.T(), deletedMapping) +} + +func (s *ResourceMappingsSuite) Test_DeleteResourceMappingWithUnknownIdFails() { + deleted, err := s.db.PolicyClient.DeleteResourceMapping(s.ctx, nonExistentResourceMappingUUID) + assert.NotNil(s.T(), err) + assert.Nil(s.T(), deleted) + assert.ErrorIs(s.T(), err, db.ErrNotFound) +} + +func TestResourceMappingsSuite(t *testing.T) { + if testing.Short() { + t.Skip("skipping resource mappings integration tests") + } + suite.Run(t, new(ResourceMappingsSuite)) +} diff --git a/internal/db/db.go b/internal/db/db.go index 5187ea5841..d4dae863d7 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -7,7 +7,6 @@ import ( "net" sq "github.com/Masterminds/squirrel" - "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgxpool" diff --git a/internal/fixtures/fixtures.go b/internal/fixtures/fixtures.go index d2d1f13a97..e1ebcfdcf6 100644 --- a/internal/fixtures/fixtures.go +++ b/internal/fixtures/fixtures.go @@ -46,6 +46,12 @@ type FixtureDataAttributeValue struct { Active bool `yaml:"active"` } +type FixtureDataValueMember struct { + Id string `yaml:"id"` + ValueID string `yaml:"value_id"` + MemberID string `yaml:"member_id"` +} + type FixtureDataAttributeValueKeyAccessServer struct { ValueID string `yaml:"value_id"` KeyAccessServerID string `yaml:"key_access_server_id"` @@ -123,6 +129,10 @@ type FixtureData struct { Metadata FixtureMetadata `yaml:"metadata"` Data map[string]FixtureDataKasRegistry `yaml:"data"` } `yaml:"kas_registry"` + ValueMembers struct { + Metadata FixtureMetadata `yaml:"metadata"` + Data map[string]FixtureDataValueMember `yaml:"data"` + } `yaml:"value_members"` } func LoadFixtureData(file string) { @@ -176,6 +186,14 @@ func (f *Fixtures) GetAttributeValueKey(key string) FixtureDataAttributeValue { return av } +func (f *Fixtures) GetValueMemberKey(key string) FixtureDataValueMember { + if fixtureData.ValueMembers.Data[key].Id == "" { + slog.Error("could not find value-members", slog.String("id", key)) + panic("could not find value-members") + } + return fixtureData.ValueMembers.Data[key] +} + func (f *Fixtures) GetSubjectMappingKey(key string) FixtureDataSubjectMapping { sm, ok := fixtureData.SubjectMappings.Data[key] if !ok || sm.Id == "" { @@ -225,6 +243,8 @@ func (f *Fixtures) Provision() { a := f.provisionAttribute() slog.Info("📦 provisioning attribute value data") aV := f.provisionAttributeValues() + slog.Info("📦 provisioning value member data") + vM := f.provisionValueMembers() slog.Info("📦 provisioning subject condition set data") sc := f.provisionSubjectConditionSet() slog.Info("📦 provisioning subject mapping data") @@ -242,6 +262,7 @@ func (f *Fixtures) Provision() { slog.Int64("namespaces", n), slog.Int64("attributes", a), slog.Int64("attribute_values", aV), + slog.Int64("value_members", vM), slog.Int64("subject_mappings", sM), slog.Int64("subject_condition_set", sc), slog.Int64("resource_mappings", rM), @@ -304,6 +325,18 @@ func (f *Fixtures) provisionAttributeValues() int64 { return f.provision(fixtureData.AttributeValues.Metadata.TableName, fixtureData.AttributeValues.Metadata.Columns, values) } +func (f *Fixtures) provisionValueMembers() int64 { + values := make([][]string, 0, len(fixtureData.ValueMembers.Data)) + for _, d := range fixtureData.ValueMembers.Data { + values = append(values, []string{ + f.db.StringWrap(d.Id), + f.db.StringWrap(d.ValueID), + f.db.StringWrap(d.MemberID), + }) + } + return f.provision(fixtureData.ValueMembers.Metadata.TableName, fixtureData.ValueMembers.Metadata.Columns, values) +} + func (f *Fixtures) provisionSubjectConditionSet() int64 { values := make([][]string, 0, len(fixtureData.SubjectConditionSet.Data)) for _, d := range fixtureData.SubjectConditionSet.Data { diff --git a/internal/fixtures/policy_fixtures.yaml b/internal/fixtures/policy_fixtures.yaml index f6c881ed5a..5d75d99921 100644 --- a/internal/fixtures/policy_fixtures.yaml +++ b/internal/fixtures/policy_fixtures.yaml @@ -140,10 +140,10 @@ attribute_values: attribute_definition_id: 6a261d68-0899-4e17-bb2f-124abba7c09c value: value2 members: - # example.com/attr/attr2/value/value1 - - 0fd363db-27b1-4210-b77b-8c82fe044d41 - # example.net/attr/attr1/value/value1 - - 532e5957-28f7-466d-91e2-493e9431cd83 + # pivots value: example.com/attr/attr2/value/value1 + - bf461e97-a918-4aa5-83ad-9bb768a58d12 + # pivots value: example.net/attr/attr1/value/value1 + - ddd9c539-2a2b-47ba-aad3-95b54dd022ef active: true example.com/attr/attr2/value/value1: @@ -187,6 +187,22 @@ attribute_value_key_access_servers: - value_id: 74babca6-016f-4f3e-a99b-4e46ea8d0fd8 key_access_server_id: e36640a6-61c5-4d4c-a45b-0e0a26d1c45f +value_members: + metadata: + table_name: value_members + columns: + - id + - value_id + - member_id + data: + member1: + id: bf461e97-a918-4aa5-83ad-9bb768a58d12 + value_id: 2fe8dea1-3555-498c-afe9-99724f35f3d3 + member_id: 0fd363db-27b1-4210-b77b-8c82fe044d41 + member2: + id: ddd9c539-2a2b-47ba-aad3-95b54dd022ef + value_id: 2fe8dea1-3555-498c-afe9-99724f35f3d3 + member_id: 532e5957-28f7-466d-91e2-493e9431cd83 ## # Subject Mappings -> 1 Group of Subject Condition Sets ## diff --git a/internal/set/set.go b/internal/set/set.go new file mode 100644 index 0000000000..8493f61e8c --- /dev/null +++ b/internal/set/set.go @@ -0,0 +1,103 @@ +package set + +type Set struct { + set map[interface{}]struct{} +} + +func NewSet() *Set { + return &Set{set: make(map[interface{}]struct{})} +} + +func (s *Set) Add(i interface{}) { + s.set[i] = struct{}{} +} + +func (s *Set) Remove(i interface{}) { + delete(s.set, i) +} + +func (s *Set) Contains(i interface{}) bool { + _, ok := s.set[i] + return ok +} + +func (s *Set) Len() int { + return len(s.set) +} + +func (s *Set) ToSlice() []interface{} { + slice := make([]interface{}, 0, len(s.set)) + for i := range s.set { + slice = append(slice, i) + } + return slice +} + +func (s *Set) Each(f func(interface{})) { + for i := range s.set { + f(i) + } +} + +func (s *Set) Iter() <-chan interface{} { + ch := make(chan interface{}) + go func() { + for i := range s.set { + ch <- i + } + close(ch) + }() + return ch +} + +func (s *Set) Union(other *Set) *Set { + union := NewSet() + for i := range s.set { + union.Add(i) + } + for i := range other.set { + union.Add(i) + } + return union +} + +func (s *Set) Intersect(other *Set) *Set { + intersect := NewSet() + for i := range s.set { + if other.Contains(i) { + intersect.Add(i) + } + } + return intersect +} + +func (s *Set) Difference(other *Set) *Set { + difference := NewSet() + for i := range s.set { + if !other.Contains(i) { + difference.Add(i) + } + } + return difference +} + +func (s *Set) IsSubset(other *Set) bool { + for i := range s.set { + if !other.Contains(i) { + return false + } + } + return true +} + +func (s *Set) IsSuperset(other *Set) bool { + return other.IsSubset(s) +} + +func (s *Set) Equal(other *Set) bool { + return s.IsSubset(other) && s.IsSuperset(other) +} + +func (s *Set) Clear() { + s.set = make(map[interface{}]struct{}) +} diff --git a/migrations/20240223000000_create_val_members.md b/migrations/20240223000000_create_val_members.md new file mode 100644 index 0000000000..e7efa6c59c --- /dev/null +++ b/migrations/20240223000000_create_val_members.md @@ -0,0 +1,29 @@ +# Diagram for 20240223000000_create_val_members.sql + +```mermaid +--- +title: Attribute Value Mermaid Diagram +nodes: | +--- + +erDiagram + AttributeValue ||--o{ ValueMember: "has group members" + + AttributeValue { + uuid id PK + uuid namespace_id FK + uuid attribute_definition_id FK + varchar value + uuid[] members FK "Optional grouping of values" + jsonb metadata + compIdx comp_key UK "ns_id + ad_id + value" + bool active + } + + ValueMember { + uuid id PK + uuid value_id FK + uuid member_id FK + } + +``` diff --git a/migrations/20240223000000_create_val_members.sql b/migrations/20240223000000_create_val_members.sql new file mode 100644 index 0000000000..2bf0b0e568 --- /dev/null +++ b/migrations/20240223000000_create_val_members.sql @@ -0,0 +1,121 @@ +-- +goose Up +-- +goose StatementBegin + +CREATE TABLE IF NOT EXISTS value_members +( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + value_id UUID NOT NULL REFERENCES attribute_values(id), + member_id UUID NOT NULL REFERENCES attribute_values(id), + UNIQUE (value_id, member_id) +); + +-- trigger to update attribute_values.members when value_member is added +CREATE OR REPLACE FUNCTION update_attribute_values_members() +RETURNS TRIGGER AS $$ +BEGIN + IF (TG_OP = 'INSERT') THEN + UPDATE attribute_values + SET members = array_append(members, NEW.id) + WHERE id = NEW.value_id; + -- AND NEW.id <> ALL(members); + END IF; + RETURN NULL; +END +$$ language 'plpgsql'; + +CREATE TRIGGER value_members_insert + AFTER + INSERT + ON value_members + FOR EACH ROW + EXECUTE PROCEDURE update_attribute_values_members(); + + +-- trigger to update attribute_values.members when value_member is deleted +CREATE OR REPLACE FUNCTION delete_attribute_values_members() +RETURNS TRIGGER AS $$ +BEGIN + IF (TG_OP = 'DELETE') THEN + UPDATE attribute_values + SET members = array_remove(members, OLD.id) + WHERE id = OLD.value_id; + END IF; + RETURN NULL; +END +$$ language 'plpgsql'; + +CREATE TRIGGER value_members_delete + AFTER + DELETE + ON value_members + FOR EACH ROW + EXECUTE PROCEDURE delete_attribute_values_members(); + + +-- trigger to update attribute_values.members when attribute_value is deleted +CREATE OR REPLACE FUNCTION delete_attribute_values_members_on_attribute_value_delete() +RETURNS TRIGGER AS $$ +BEGIN + IF (TG_OP = 'DELETE') THEN + UPDATE attribute_values + SET members = array_remove(members, value_members.id) + FROM value_members + WHERE value_members.member_id = OLD.id; + END IF; + RETURN NULL; +END +$$ language 'plpgsql'; + +CREATE TRIGGER attribute_values_delete + AFTER + DELETE + ON attribute_values + FOR EACH ROW + EXECUTE PROCEDURE delete_attribute_values_members_on_attribute_value_delete(); + +-- trigger to update value_members when attribute_value is deleted +CREATE OR REPLACE FUNCTION delete_value_members_on_attribute_value_delete() +RETURNS TRIGGER AS $$ +BEGIN + IF (TG_OP = 'DELETE') THEN + DELETE FROM value_members + WHERE value_members.value_id = OLD.id OR value_members.member_id = OLD.id; + END IF; + RETURN NULL; +END +$$ language 'plpgsql'; + +CREATE TRIGGER attribute_values_delete_value_members + AFTER + DELETE + ON attribute_values + FOR EACH ROW + EXECUTE PROCEDURE delete_value_members_on_attribute_value_delete(); + +-- trigger to update value_members when attribute_value is updated +CREATE OR REPLACE FUNCTION update_value_members_on_attribute_value_update() +RETURNS TRIGGER AS $$ +BEGIN + IF (TG_OP = 'UPDATE') THEN + UPDATE value_members + SET value_id = NEW.id + WHERE value_id = OLD.id; + END IF; + RETURN NULL; +END +$$ language 'plpgsql'; + +CREATE TRIGGER attribute_values_update_value_members + AFTER + UPDATE + ON attribute_values + FOR EACH ROW + EXECUTE PROCEDURE update_value_members_on_attribute_value_update(); + +-- +goose StatementEnd + +-- +goose Down + +-- +goose StatementBegin +DROP TABLE IF EXISTS value_members; +-- +goose StatementEnd diff --git a/protocol/go/policy/attributes/attributes.pb.go b/protocol/go/policy/attributes/attributes.pb.go index 2f9b11d86d..969655e3cc 100644 --- a/protocol/go/policy/attributes/attributes.pb.go +++ b/protocol/go/policy/attributes/attributes.pb.go @@ -205,7 +205,7 @@ type Value struct { Attribute *Attribute `protobuf:"bytes,2,opt,name=attribute,proto3" json:"attribute,omitempty"` Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` // list of attribute values that this value is related to (attribute group) - Members []string `protobuf:"bytes,4,rep,name=members,proto3" json:"members,omitempty"` + Members []*Value `protobuf:"bytes,4,rep,name=members,proto3" json:"members,omitempty"` // list of key access servers Grants []*kasregistry.KeyAccessServer `protobuf:"bytes,5,rep,name=grants,proto3" json:"grants,omitempty"` Fqn string `protobuf:"bytes,6,opt,name=fqn,proto3" json:"fqn,omitempty"` @@ -268,7 +268,7 @@ func (x *Value) GetValue() string { return "" } -func (x *Value) GetMembers() []string { +func (x *Value) GetMembers() []*Value { if x != nil { return x.Members } @@ -2032,453 +2032,454 @@ var file_policy_attributes_attributes_proto_rawDesc = []byte{ 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xad, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xc7, 0x02, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x12, 0x34, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x71, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x12, 0x32, 0x0a, 0x06, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x7f, - 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, - 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x6e, 0x0a, 0x18, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x2f, - 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, - 0x62, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x49, 0x64, 0x22, 0x46, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x56, 0x0a, 0x16, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x22, 0x2d, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, - 0x69, 0x64, 0x22, 0x52, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x3d, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x66, 0x71, 0x6e, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x04, 0x66, 0x71, 0x6e, 0x73, 0x22, 0x8e, 0x02, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x66, 0x71, - 0x6e, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x71, - 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x66, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x6b, 0x0a, 0x17, 0x46, 0x71, 0x6e, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x34, + 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x06, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x12, 0x32, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x7f, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, + 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x6e, 0x0a, 0x18, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x62, 0x0a, 0x14, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, + 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x46, 0x0a, + 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x56, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3c, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x2d, 0x0a, + 0x13, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x52, 0x0a, 0x14, + 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x22, 0x3d, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x22, + 0x8e, 0x02, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x66, 0x71, 0x6e, 0x5f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x12, 0x66, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x1a, 0x6b, 0x0a, 0x17, 0x46, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x41, 0x6e, 0x64, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xdf, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0c, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x49, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, + 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, + 0x01, 0x01, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x75, 0x6c, 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, 0x22, 0x55, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, + 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 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, 0x55, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdf, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x29, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, - 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x49, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, - 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, 0x01, 0x01, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, - 0x75, 0x6c, 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, 0x22, 0x55, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, + 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x34, + 0x0a, 0x1a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, + 0x52, 0x02, 0x69, 0x64, 0x22, 0x59, 0x0a, 0x1b, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, - 0xbb, 0x01, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, - 0x69, 0x64, 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, 0x55, 0x0a, - 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x22, 0x34, 0x0a, 0x1a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, - 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x59, 0x0a, 0x1b, 0x44, 0x65, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x32, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, + 0x32, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x22, 0x76, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, + 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, + 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4f, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x1b, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0c, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 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, 0x4e, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0xda, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x19, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x76, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, - 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, - 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4f, - 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, - 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, - 0xb5, 0x01, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x29, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, - 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 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, 0x4e, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xda, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 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, 0x4e, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, 0x0a, 0x1f, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, - 0x52, 0x0a, 0x20, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x22, 0x95, 0x01, 0x0a, 0x27, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x96, 0x01, 0x0a, 0x28, - 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 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, 0x4e, + 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x22, 0x97, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, - 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, + 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, + 0x0a, 0x1f, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, + 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x52, 0x0a, 0x20, 0x44, 0x65, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x95, 0x01, + 0x0a, 0x27, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x96, 0x01, 0x0a, 0x28, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, + 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, - 0x01, 0x0a, 0x2a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x97, + 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, - 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, - 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x23, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x22, 0x86, 0x01, 0x0a, 0x24, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x25, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x2a, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x23, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x24, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, + 0x72, 0x76, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x25, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, - 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, - 0xb3, 0x01, 0x0a, 0x15, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x28, 0x0a, 0x24, 0x41, 0x54, 0x54, - 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, + 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, + 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x88, + 0x01, 0x0a, 0x26, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0xb3, 0x01, 0x0a, 0x15, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x45, + 0x6e, 0x75, 0x6d, 0x12, 0x28, 0x0a, 0x24, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, - 0x41, 0x4c, 0x4c, 0x5f, 0x4f, 0x46, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x54, 0x54, 0x52, - 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x41, 0x4e, 0x59, 0x5f, 0x4f, 0x46, 0x10, 0x02, 0x12, 0x26, 0x0a, - 0x22, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x48, 0x49, 0x45, 0x52, 0x41, 0x52, - 0x43, 0x48, 0x59, 0x10, 0x03, 0x32, 0xc7, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x0e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, + 0x1f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x41, 0x4c, 0x4c, 0x5f, 0x4f, 0x46, + 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, + 0x52, 0x55, 0x4c, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x41, + 0x4e, 0x59, 0x5f, 0x4f, 0x46, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, 0x41, 0x54, 0x54, 0x52, 0x49, + 0x42, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4c, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, + 0x4e, 0x55, 0x4d, 0x5f, 0x48, 0x49, 0x45, 0x52, 0x41, 0x52, 0x43, 0x48, 0x59, 0x10, 0x03, 0x32, + 0xc7, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x46, 0x71, 0x6e, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x66, 0x71, 0x6e, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, - 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, - 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, - 0x2a, 0x32, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0x8e, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, - 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x91, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, - 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, + 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, + 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, + 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, 0x73, 0x12, 0x32, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x42, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x71, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, + 0x11, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x66, + 0x71, 0x6e, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x32, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0xa6, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8e, 0x01, + 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x91, + 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, - 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, - 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x12, 0xea, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x32, + 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, 0x18, 0x44, + 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0xea, 0x01, 0x0a, 0x22, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0xdb, 0x01, 0x0a, 0x1c, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, 0x2f, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, + 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x61, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0xe1, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, - 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0xdb, 0x01, - 0x0a, 0x1c, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x22, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0xe1, 0x01, 0x0a, 0x1e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, - 0xd8, 0x01, 0x0a, 0x25, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2e, 0x70, - 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 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, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x41, 0x58, 0xaa, 0x02, 0x11, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, + 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, + 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0xd8, 0x01, 0x0a, 0x25, 0x69, 0x6f, + 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x42, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 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, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0xa2, 0x02, 0x03, 0x50, 0x41, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, + 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2549,75 +2550,76 @@ var file_policy_attributes_attributes_proto_depIdxs = []int32{ 39, // 4: policy.attributes.Attribute.active:type_name -> google.protobuf.BoolValue 40, // 5: policy.attributes.Attribute.metadata:type_name -> common.Metadata 1, // 6: policy.attributes.Value.attribute:type_name -> policy.attributes.Attribute - 38, // 7: policy.attributes.Value.grants:type_name -> kasregistry.KeyAccessServer - 39, // 8: policy.attributes.Value.active:type_name -> google.protobuf.BoolValue - 40, // 9: policy.attributes.Value.metadata:type_name -> common.Metadata - 1, // 10: policy.attributes.AttributeAndValue.attribute:type_name -> policy.attributes.Attribute - 2, // 11: policy.attributes.AttributeAndValue.value:type_name -> policy.attributes.Value - 41, // 12: policy.attributes.ListAttributesRequest.state:type_name -> common.ActiveStateEnum - 1, // 13: policy.attributes.ListAttributesResponse.attributes:type_name -> policy.attributes.Attribute - 1, // 14: policy.attributes.GetAttributeResponse.attribute:type_name -> policy.attributes.Attribute - 36, // 15: policy.attributes.GetAttributesByValueFqnsResponse.fqn_attribute_values:type_name -> policy.attributes.GetAttributesByValueFqnsResponse.FqnAttributeValuesEntry - 0, // 16: policy.attributes.CreateAttributeRequest.rule:type_name -> policy.attributes.AttributeRuleTypeEnum - 42, // 17: policy.attributes.CreateAttributeRequest.metadata:type_name -> common.MetadataMutable - 1, // 18: policy.attributes.CreateAttributeResponse.attribute:type_name -> policy.attributes.Attribute - 42, // 19: policy.attributes.UpdateAttributeRequest.metadata:type_name -> common.MetadataMutable - 43, // 20: policy.attributes.UpdateAttributeRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 1, // 21: policy.attributes.UpdateAttributeResponse.attribute:type_name -> policy.attributes.Attribute - 1, // 22: policy.attributes.DeactivateAttributeResponse.attribute:type_name -> policy.attributes.Attribute - 2, // 23: policy.attributes.GetAttributeValueResponse.value:type_name -> policy.attributes.Value - 41, // 24: policy.attributes.ListAttributeValuesRequest.state:type_name -> common.ActiveStateEnum - 2, // 25: policy.attributes.ListAttributeValuesResponse.values:type_name -> policy.attributes.Value - 42, // 26: policy.attributes.CreateAttributeValueRequest.metadata:type_name -> common.MetadataMutable - 2, // 27: policy.attributes.CreateAttributeValueResponse.value:type_name -> policy.attributes.Value - 42, // 28: policy.attributes.UpdateAttributeValueRequest.metadata:type_name -> common.MetadataMutable - 43, // 29: policy.attributes.UpdateAttributeValueRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 2, // 30: policy.attributes.UpdateAttributeValueResponse.value:type_name -> policy.attributes.Value - 2, // 31: policy.attributes.DeactivateAttributeValueResponse.value:type_name -> policy.attributes.Value - 4, // 32: policy.attributes.AssignKeyAccessServerToAttributeRequest.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer - 4, // 33: policy.attributes.AssignKeyAccessServerToAttributeResponse.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer - 4, // 34: policy.attributes.RemoveKeyAccessServerFromAttributeRequest.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer - 4, // 35: policy.attributes.RemoveKeyAccessServerFromAttributeResponse.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer - 5, // 36: policy.attributes.AssignKeyAccessServerToValueRequest.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer - 5, // 37: policy.attributes.AssignKeyAccessServerToValueResponse.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer - 5, // 38: policy.attributes.RemoveKeyAccessServerFromValueRequest.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer - 5, // 39: policy.attributes.RemoveKeyAccessServerFromValueResponse.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer - 3, // 40: policy.attributes.GetAttributesByValueFqnsResponse.FqnAttributeValuesEntry.value:type_name -> policy.attributes.AttributeAndValue - 6, // 41: policy.attributes.AttributesService.ListAttributes:input_type -> policy.attributes.ListAttributesRequest - 20, // 42: policy.attributes.AttributesService.ListAttributeValues:input_type -> policy.attributes.ListAttributeValuesRequest - 8, // 43: policy.attributes.AttributesService.GetAttribute:input_type -> policy.attributes.GetAttributeRequest - 10, // 44: policy.attributes.AttributesService.GetAttributesByValueFqns:input_type -> policy.attributes.GetAttributesByValueFqnsRequest - 12, // 45: policy.attributes.AttributesService.CreateAttribute:input_type -> policy.attributes.CreateAttributeRequest - 14, // 46: policy.attributes.AttributesService.UpdateAttribute:input_type -> policy.attributes.UpdateAttributeRequest - 16, // 47: policy.attributes.AttributesService.DeactivateAttribute:input_type -> policy.attributes.DeactivateAttributeRequest - 18, // 48: policy.attributes.AttributesService.GetAttributeValue:input_type -> policy.attributes.GetAttributeValueRequest - 22, // 49: policy.attributes.AttributesService.CreateAttributeValue:input_type -> policy.attributes.CreateAttributeValueRequest - 24, // 50: policy.attributes.AttributesService.UpdateAttributeValue:input_type -> policy.attributes.UpdateAttributeValueRequest - 26, // 51: policy.attributes.AttributesService.DeactivateAttributeValue:input_type -> policy.attributes.DeactivateAttributeValueRequest - 28, // 52: policy.attributes.AttributesService.AssignKeyAccessServerToAttribute:input_type -> policy.attributes.AssignKeyAccessServerToAttributeRequest - 30, // 53: policy.attributes.AttributesService.RemoveKeyAccessServerFromAttribute:input_type -> policy.attributes.RemoveKeyAccessServerFromAttributeRequest - 32, // 54: policy.attributes.AttributesService.AssignKeyAccessServerToValue:input_type -> policy.attributes.AssignKeyAccessServerToValueRequest - 34, // 55: policy.attributes.AttributesService.RemoveKeyAccessServerFromValue:input_type -> policy.attributes.RemoveKeyAccessServerFromValueRequest - 7, // 56: policy.attributes.AttributesService.ListAttributes:output_type -> policy.attributes.ListAttributesResponse - 21, // 57: policy.attributes.AttributesService.ListAttributeValues:output_type -> policy.attributes.ListAttributeValuesResponse - 9, // 58: policy.attributes.AttributesService.GetAttribute:output_type -> policy.attributes.GetAttributeResponse - 11, // 59: policy.attributes.AttributesService.GetAttributesByValueFqns:output_type -> policy.attributes.GetAttributesByValueFqnsResponse - 13, // 60: policy.attributes.AttributesService.CreateAttribute:output_type -> policy.attributes.CreateAttributeResponse - 15, // 61: policy.attributes.AttributesService.UpdateAttribute:output_type -> policy.attributes.UpdateAttributeResponse - 17, // 62: policy.attributes.AttributesService.DeactivateAttribute:output_type -> policy.attributes.DeactivateAttributeResponse - 19, // 63: policy.attributes.AttributesService.GetAttributeValue:output_type -> policy.attributes.GetAttributeValueResponse - 23, // 64: policy.attributes.AttributesService.CreateAttributeValue:output_type -> policy.attributes.CreateAttributeValueResponse - 25, // 65: policy.attributes.AttributesService.UpdateAttributeValue:output_type -> policy.attributes.UpdateAttributeValueResponse - 27, // 66: policy.attributes.AttributesService.DeactivateAttributeValue:output_type -> policy.attributes.DeactivateAttributeValueResponse - 29, // 67: policy.attributes.AttributesService.AssignKeyAccessServerToAttribute:output_type -> policy.attributes.AssignKeyAccessServerToAttributeResponse - 31, // 68: policy.attributes.AttributesService.RemoveKeyAccessServerFromAttribute:output_type -> policy.attributes.RemoveKeyAccessServerFromAttributeResponse - 33, // 69: policy.attributes.AttributesService.AssignKeyAccessServerToValue:output_type -> policy.attributes.AssignKeyAccessServerToValueResponse - 35, // 70: policy.attributes.AttributesService.RemoveKeyAccessServerFromValue:output_type -> policy.attributes.RemoveKeyAccessServerFromValueResponse - 56, // [56:71] is the sub-list for method output_type - 41, // [41:56] is the sub-list for method input_type - 41, // [41:41] is the sub-list for extension type_name - 41, // [41:41] is the sub-list for extension extendee - 0, // [0:41] is the sub-list for field type_name + 2, // 7: policy.attributes.Value.members:type_name -> policy.attributes.Value + 38, // 8: policy.attributes.Value.grants:type_name -> kasregistry.KeyAccessServer + 39, // 9: policy.attributes.Value.active:type_name -> google.protobuf.BoolValue + 40, // 10: policy.attributes.Value.metadata:type_name -> common.Metadata + 1, // 11: policy.attributes.AttributeAndValue.attribute:type_name -> policy.attributes.Attribute + 2, // 12: policy.attributes.AttributeAndValue.value:type_name -> policy.attributes.Value + 41, // 13: policy.attributes.ListAttributesRequest.state:type_name -> common.ActiveStateEnum + 1, // 14: policy.attributes.ListAttributesResponse.attributes:type_name -> policy.attributes.Attribute + 1, // 15: policy.attributes.GetAttributeResponse.attribute:type_name -> policy.attributes.Attribute + 36, // 16: policy.attributes.GetAttributesByValueFqnsResponse.fqn_attribute_values:type_name -> policy.attributes.GetAttributesByValueFqnsResponse.FqnAttributeValuesEntry + 0, // 17: policy.attributes.CreateAttributeRequest.rule:type_name -> policy.attributes.AttributeRuleTypeEnum + 42, // 18: policy.attributes.CreateAttributeRequest.metadata:type_name -> common.MetadataMutable + 1, // 19: policy.attributes.CreateAttributeResponse.attribute:type_name -> policy.attributes.Attribute + 42, // 20: policy.attributes.UpdateAttributeRequest.metadata:type_name -> common.MetadataMutable + 43, // 21: policy.attributes.UpdateAttributeRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 1, // 22: policy.attributes.UpdateAttributeResponse.attribute:type_name -> policy.attributes.Attribute + 1, // 23: policy.attributes.DeactivateAttributeResponse.attribute:type_name -> policy.attributes.Attribute + 2, // 24: policy.attributes.GetAttributeValueResponse.value:type_name -> policy.attributes.Value + 41, // 25: policy.attributes.ListAttributeValuesRequest.state:type_name -> common.ActiveStateEnum + 2, // 26: policy.attributes.ListAttributeValuesResponse.values:type_name -> policy.attributes.Value + 42, // 27: policy.attributes.CreateAttributeValueRequest.metadata:type_name -> common.MetadataMutable + 2, // 28: policy.attributes.CreateAttributeValueResponse.value:type_name -> policy.attributes.Value + 42, // 29: policy.attributes.UpdateAttributeValueRequest.metadata:type_name -> common.MetadataMutable + 43, // 30: policy.attributes.UpdateAttributeValueRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 2, // 31: policy.attributes.UpdateAttributeValueResponse.value:type_name -> policy.attributes.Value + 2, // 32: policy.attributes.DeactivateAttributeValueResponse.value:type_name -> policy.attributes.Value + 4, // 33: policy.attributes.AssignKeyAccessServerToAttributeRequest.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer + 4, // 34: policy.attributes.AssignKeyAccessServerToAttributeResponse.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer + 4, // 35: policy.attributes.RemoveKeyAccessServerFromAttributeRequest.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer + 4, // 36: policy.attributes.RemoveKeyAccessServerFromAttributeResponse.attribute_key_access_server:type_name -> policy.attributes.AttributeKeyAccessServer + 5, // 37: policy.attributes.AssignKeyAccessServerToValueRequest.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer + 5, // 38: policy.attributes.AssignKeyAccessServerToValueResponse.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer + 5, // 39: policy.attributes.RemoveKeyAccessServerFromValueRequest.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer + 5, // 40: policy.attributes.RemoveKeyAccessServerFromValueResponse.value_key_access_server:type_name -> policy.attributes.ValueKeyAccessServer + 3, // 41: policy.attributes.GetAttributesByValueFqnsResponse.FqnAttributeValuesEntry.value:type_name -> policy.attributes.AttributeAndValue + 6, // 42: policy.attributes.AttributesService.ListAttributes:input_type -> policy.attributes.ListAttributesRequest + 20, // 43: policy.attributes.AttributesService.ListAttributeValues:input_type -> policy.attributes.ListAttributeValuesRequest + 8, // 44: policy.attributes.AttributesService.GetAttribute:input_type -> policy.attributes.GetAttributeRequest + 10, // 45: policy.attributes.AttributesService.GetAttributesByValueFqns:input_type -> policy.attributes.GetAttributesByValueFqnsRequest + 12, // 46: policy.attributes.AttributesService.CreateAttribute:input_type -> policy.attributes.CreateAttributeRequest + 14, // 47: policy.attributes.AttributesService.UpdateAttribute:input_type -> policy.attributes.UpdateAttributeRequest + 16, // 48: policy.attributes.AttributesService.DeactivateAttribute:input_type -> policy.attributes.DeactivateAttributeRequest + 18, // 49: policy.attributes.AttributesService.GetAttributeValue:input_type -> policy.attributes.GetAttributeValueRequest + 22, // 50: policy.attributes.AttributesService.CreateAttributeValue:input_type -> policy.attributes.CreateAttributeValueRequest + 24, // 51: policy.attributes.AttributesService.UpdateAttributeValue:input_type -> policy.attributes.UpdateAttributeValueRequest + 26, // 52: policy.attributes.AttributesService.DeactivateAttributeValue:input_type -> policy.attributes.DeactivateAttributeValueRequest + 28, // 53: policy.attributes.AttributesService.AssignKeyAccessServerToAttribute:input_type -> policy.attributes.AssignKeyAccessServerToAttributeRequest + 30, // 54: policy.attributes.AttributesService.RemoveKeyAccessServerFromAttribute:input_type -> policy.attributes.RemoveKeyAccessServerFromAttributeRequest + 32, // 55: policy.attributes.AttributesService.AssignKeyAccessServerToValue:input_type -> policy.attributes.AssignKeyAccessServerToValueRequest + 34, // 56: policy.attributes.AttributesService.RemoveKeyAccessServerFromValue:input_type -> policy.attributes.RemoveKeyAccessServerFromValueRequest + 7, // 57: policy.attributes.AttributesService.ListAttributes:output_type -> policy.attributes.ListAttributesResponse + 21, // 58: policy.attributes.AttributesService.ListAttributeValues:output_type -> policy.attributes.ListAttributeValuesResponse + 9, // 59: policy.attributes.AttributesService.GetAttribute:output_type -> policy.attributes.GetAttributeResponse + 11, // 60: policy.attributes.AttributesService.GetAttributesByValueFqns:output_type -> policy.attributes.GetAttributesByValueFqnsResponse + 13, // 61: policy.attributes.AttributesService.CreateAttribute:output_type -> policy.attributes.CreateAttributeResponse + 15, // 62: policy.attributes.AttributesService.UpdateAttribute:output_type -> policy.attributes.UpdateAttributeResponse + 17, // 63: policy.attributes.AttributesService.DeactivateAttribute:output_type -> policy.attributes.DeactivateAttributeResponse + 19, // 64: policy.attributes.AttributesService.GetAttributeValue:output_type -> policy.attributes.GetAttributeValueResponse + 23, // 65: policy.attributes.AttributesService.CreateAttributeValue:output_type -> policy.attributes.CreateAttributeValueResponse + 25, // 66: policy.attributes.AttributesService.UpdateAttributeValue:output_type -> policy.attributes.UpdateAttributeValueResponse + 27, // 67: policy.attributes.AttributesService.DeactivateAttributeValue:output_type -> policy.attributes.DeactivateAttributeValueResponse + 29, // 68: policy.attributes.AttributesService.AssignKeyAccessServerToAttribute:output_type -> policy.attributes.AssignKeyAccessServerToAttributeResponse + 31, // 69: policy.attributes.AttributesService.RemoveKeyAccessServerFromAttribute:output_type -> policy.attributes.RemoveKeyAccessServerFromAttributeResponse + 33, // 70: policy.attributes.AttributesService.AssignKeyAccessServerToValue:output_type -> policy.attributes.AssignKeyAccessServerToValueResponse + 35, // 71: policy.attributes.AttributesService.RemoveKeyAccessServerFromValue:output_type -> policy.attributes.RemoveKeyAccessServerFromValueResponse + 57, // [57:72] is the sub-list for method output_type + 42, // [42:57] is the sub-list for method input_type + 42, // [42:42] is the sub-list for extension type_name + 42, // [42:42] is the sub-list for extension extendee + 0, // [0:42] is the sub-list for field type_name } func init() { file_policy_attributes_attributes_proto_init() } diff --git a/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/AttributesProto.java b/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/AttributesProto.java index 564afb29b9..ecb6415116 100644 --- a/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/AttributesProto.java +++ b/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/AttributesProto.java @@ -220,185 +220,186 @@ public static void registerAllExtensions( "cessServerR\006grants\022\020\n\003fqn\030\007 \001(\tR\003fqn\0222\n\006" + "active\030\010 \001(\0132\032.google.protobuf.BoolValue" + "R\006active\022,\n\010metadata\030d \001(\0132\020.common.Meta" + - "dataR\010metadata\"\255\002\n\005Value\022\016\n\002id\030\001 \001(\tR\002id" + + "dataR\010metadata\"\307\002\n\005Value\022\016\n\002id\030\001 \001(\tR\002id" + "\022:\n\tattribute\030\002 \001(\0132\034.policy.attributes." + "AttributeR\tattribute\022\024\n\005value\030\003 \001(\tR\005val" + - "ue\022\030\n\007members\030\004 \003(\tR\007members\0224\n\006grants\030\005" + - " \003(\0132\034.kasregistry.KeyAccessServerR\006gran" + - "ts\022\020\n\003fqn\030\006 \001(\tR\003fqn\0222\n\006active\030\007 \001(\0132\032.g" + - "oogle.protobuf.BoolValueR\006active\022,\n\010meta" + - "data\030d \001(\0132\020.common.MetadataR\010metadata\"\177" + - "\n\021AttributeAndValue\022:\n\tattribute\030\001 \001(\0132\034" + - ".policy.attributes.AttributeR\tattribute\022" + - ".\n\005value\030\002 \001(\0132\030.policy.attributes.Value" + - "R\005value\"n\n\030AttributeKeyAccessServer\022!\n\014a" + - "ttribute_id\030\001 \001(\tR\013attributeId\022/\n\024key_ac" + - "cess_server_id\030\002 \001(\tR\021keyAccessServerId\"" + - "b\n\024ValueKeyAccessServer\022\031\n\010value_id\030\001 \001(" + - "\tR\007valueId\022/\n\024key_access_server_id\030\002 \001(\t" + - "R\021keyAccessServerId\"F\n\025ListAttributesReq" + - "uest\022-\n\005state\030\001 \001(\0162\027.common.ActiveState" + - "EnumR\005state\"V\n\026ListAttributesResponse\022<\n" + - "\nattributes\030\001 \003(\0132\034.policy.attributes.At" + - "tributeR\nattributes\"-\n\023GetAttributeReque" + - "st\022\026\n\002id\030\001 \001(\tB\006\272H\003\310\001\001R\002id\"R\n\024GetAttribu" + - "teResponse\022:\n\tattribute\030\001 \001(\0132\034.policy.a" + - "ttributes.AttributeR\tattribute\"=\n\037GetAtt" + - "ributesByValueFqnsRequest\022\032\n\004fqns\030\001 \003(\tB" + - "\006\272H\003\310\001\001R\004fqns\"\216\002\n GetAttributesByValueFq" + - "nsResponse\022}\n\024fqn_attribute_values\030\001 \003(\013" + - "2K.policy.attributes.GetAttributesByValu" + - "eFqnsResponse.FqnAttributeValuesEntryR\022f" + - "qnAttributeValues\032k\n\027FqnAttributeValuesE" + - "ntry\022\020\n\003key\030\001 \001(\tR\003key\022:\n\005value\030\002 \001(\0132$." + - "policy.attributes.AttributeAndValueR\005val" + - "ue:\0028\001\"\337\001\n\026CreateAttributeRequest\022)\n\014nam" + - "espace_id\030\001 \001(\tB\006\272H\003\310\001\001R\013namespaceId\022\032\n\004" + - "name\030\002 \001(\tB\006\272H\003\310\001\001R\004name\022I\n\004rule\030\003 \001(\0162(" + - ".policy.attributes.AttributeRuleTypeEnum" + - "B\013\272H\010\202\001\002\020\001\310\001\001R\004rule\0223\n\010metadata\030d \001(\0132\027." + - "common.MetadataMutableR\010metadata\"U\n\027Crea" + - "teAttributeResponse\022:\n\tattribute\030\001 \001(\0132\034" + - ".policy.attributes.AttributeR\tattribute\"" + - "\273\001\n\026UpdateAttributeRequest\022\026\n\002id\030\001 \001(\tB\006" + - "\272H\003\310\001\001R\002id\0223\n\010metadata\030d \001(\0132\027.common.Me" + - "tadataMutableR\010metadata\022T\n\030metadata_upda" + - "te_behavior\030e \001(\0162\032.common.MetadataUpdat" + - "eEnumR\026metadataUpdateBehavior\"U\n\027UpdateA" + - "ttributeResponse\022:\n\tattribute\030\001 \001(\0132\034.po" + - "licy.attributes.AttributeR\tattribute\"4\n\032" + - "DeactivateAttributeRequest\022\026\n\002id\030\001 \001(\tB\006" + - "\272H\003\310\001\001R\002id\"Y\n\033DeactivateAttributeRespons" + - "e\022:\n\tattribute\030\001 \001(\0132\034.policy.attributes" + - ".AttributeR\tattribute\"2\n\030GetAttributeVal" + - "ueRequest\022\026\n\002id\030\001 \001(\tB\006\272H\003\310\001\001R\002id\"K\n\031Get" + - "AttributeValueResponse\022.\n\005value\030\001 \001(\0132\030." + - "policy.attributes.ValueR\005value\"v\n\032ListAt" + - "tributeValuesRequest\022)\n\014attribute_id\030\001 \001" + - "(\tB\006\272H\003\310\001\001R\013attributeId\022-\n\005state\030\002 \001(\0162\027" + - ".common.ActiveStateEnumR\005state\"O\n\033ListAt" + - "tributeValuesResponse\0220\n\006values\030\001 \003(\0132\030." + - "policy.attributes.ValueR\006values\"\265\001\n\033Crea" + - "teAttributeValueRequest\022)\n\014attribute_id\030" + - "\001 \001(\tB\006\272H\003\310\001\001R\013attributeId\022\034\n\005value\030\002 \001(" + - "\tB\006\272H\003\310\001\001R\005value\022\030\n\007members\030\003 \003(\tR\007membe" + - "rs\0223\n\010metadata\030d \001(\0132\027.common.MetadataMu" + - "tableR\010metadata\"N\n\034CreateAttributeValueR" + - "esponse\022.\n\005value\030\001 \001(\0132\030.policy.attribut" + - "es.ValueR\005value\"\332\001\n\033UpdateAttributeValue" + - "Request\022\026\n\002id\030\001 \001(\tB\006\272H\003\310\001\001R\002id\022\030\n\007membe" + - "rs\030\004 \003(\tR\007members\0223\n\010metadata\030d \001(\0132\027.co" + - "mmon.MetadataMutableR\010metadata\022T\n\030metada" + - "ta_update_behavior\030e \001(\0162\032.common.Metada" + - "taUpdateEnumR\026metadataUpdateBehavior\"N\n\034" + - "UpdateAttributeValueResponse\022.\n\005value\030\001 " + - "\001(\0132\030.policy.attributes.ValueR\005value\"9\n\037" + - "DeactivateAttributeValueRequest\022\026\n\002id\030\001 " + - "\001(\tB\006\272H\003\310\001\001R\002id\"R\n DeactivateAttributeVa" + - "lueResponse\022.\n\005value\030\001 \001(\0132\030.policy.attr" + - "ibutes.ValueR\005value\"\225\001\n\'AssignKeyAccessS" + - "erverToAttributeRequest\022j\n\033attribute_key" + - "_access_server\030\001 \001(\0132+.policy.attributes" + - ".AttributeKeyAccessServerR\030attributeKeyA" + - "ccessServer\"\226\001\n(AssignKeyAccessServerToA" + - "ttributeResponse\022j\n\033attribute_key_access" + - "_server\030\001 \001(\0132+.policy.attributes.Attrib" + - "uteKeyAccessServerR\030attributeKeyAccessSe" + - "rver\"\227\001\n)RemoveKeyAccessServerFromAttrib" + - "uteRequest\022j\n\033attribute_key_access_serve" + - "r\030\001 \001(\0132+.policy.attributes.AttributeKey" + - "AccessServerR\030attributeKeyAccessServer\"\230" + - "\001\n*RemoveKeyAccessServerFromAttributeRes" + - "ponse\022j\n\033attribute_key_access_server\030\001 \001" + - "(\0132+.policy.attributes.AttributeKeyAcces" + - "sServerR\030attributeKeyAccessServer\"\205\001\n#As" + - "signKeyAccessServerToValueRequest\022^\n\027val" + + "ue\0222\n\007members\030\004 \003(\0132\030.policy.attributes." + + "ValueR\007members\0224\n\006grants\030\005 \003(\0132\034.kasregi" + + "stry.KeyAccessServerR\006grants\022\020\n\003fqn\030\006 \001(" + + "\tR\003fqn\0222\n\006active\030\007 \001(\0132\032.google.protobuf" + + ".BoolValueR\006active\022,\n\010metadata\030d \001(\0132\020.c" + + "ommon.MetadataR\010metadata\"\177\n\021AttributeAnd" + + "Value\022:\n\tattribute\030\001 \001(\0132\034.policy.attrib" + + "utes.AttributeR\tattribute\022.\n\005value\030\002 \001(\013" + + "2\030.policy.attributes.ValueR\005value\"n\n\030Att" + + "ributeKeyAccessServer\022!\n\014attribute_id\030\001 " + + "\001(\tR\013attributeId\022/\n\024key_access_server_id" + + "\030\002 \001(\tR\021keyAccessServerId\"b\n\024ValueKeyAcc" + + "essServer\022\031\n\010value_id\030\001 \001(\tR\007valueId\022/\n\024" + + "key_access_server_id\030\002 \001(\tR\021keyAccessSer" + + "verId\"F\n\025ListAttributesRequest\022-\n\005state\030" + + "\001 \001(\0162\027.common.ActiveStateEnumR\005state\"V\n" + + "\026ListAttributesResponse\022<\n\nattributes\030\001 " + + "\003(\0132\034.policy.attributes.AttributeR\nattri" + + "butes\"-\n\023GetAttributeRequest\022\026\n\002id\030\001 \001(\t" + + "B\006\272H\003\310\001\001R\002id\"R\n\024GetAttributeResponse\022:\n\t" + + "attribute\030\001 \001(\0132\034.policy.attributes.Attr" + + "ibuteR\tattribute\"=\n\037GetAttributesByValue" + + "FqnsRequest\022\032\n\004fqns\030\001 \003(\tB\006\272H\003\310\001\001R\004fqns\"" + + "\216\002\n GetAttributesByValueFqnsResponse\022}\n\024" + + "fqn_attribute_values\030\001 \003(\0132K.policy.attr" + + "ibutes.GetAttributesByValueFqnsResponse." + + "FqnAttributeValuesEntryR\022fqnAttributeVal" + + "ues\032k\n\027FqnAttributeValuesEntry\022\020\n\003key\030\001 " + + "\001(\tR\003key\022:\n\005value\030\002 \001(\0132$.policy.attribu" + + "tes.AttributeAndValueR\005value:\0028\001\"\337\001\n\026Cre" + + "ateAttributeRequest\022)\n\014namespace_id\030\001 \001(" + + "\tB\006\272H\003\310\001\001R\013namespaceId\022\032\n\004name\030\002 \001(\tB\006\272H" + + "\003\310\001\001R\004name\022I\n\004rule\030\003 \001(\0162(.policy.attrib" + + "utes.AttributeRuleTypeEnumB\013\272H\010\202\001\002\020\001\310\001\001R" + + "\004rule\0223\n\010metadata\030d \001(\0132\027.common.Metadat" + + "aMutableR\010metadata\"U\n\027CreateAttributeRes" + + "ponse\022:\n\tattribute\030\001 \001(\0132\034.policy.attrib" + + "utes.AttributeR\tattribute\"\273\001\n\026UpdateAttr" + + "ibuteRequest\022\026\n\002id\030\001 \001(\tB\006\272H\003\310\001\001R\002id\0223\n\010" + + "metadata\030d \001(\0132\027.common.MetadataMutableR" + + "\010metadata\022T\n\030metadata_update_behavior\030e " + + "\001(\0162\032.common.MetadataUpdateEnumR\026metadat" + + "aUpdateBehavior\"U\n\027UpdateAttributeRespon" + + "se\022:\n\tattribute\030\001 \001(\0132\034.policy.attribute" + + "s.AttributeR\tattribute\"4\n\032DeactivateAttr" + + "ibuteRequest\022\026\n\002id\030\001 \001(\tB\006\272H\003\310\001\001R\002id\"Y\n\033" + + "DeactivateAttributeResponse\022:\n\tattribute" + + "\030\001 \001(\0132\034.policy.attributes.AttributeR\tat" + + "tribute\"2\n\030GetAttributeValueRequest\022\026\n\002i" + + "d\030\001 \001(\tB\006\272H\003\310\001\001R\002id\"K\n\031GetAttributeValue" + + "Response\022.\n\005value\030\001 \001(\0132\030.policy.attribu" + + "tes.ValueR\005value\"v\n\032ListAttributeValuesR" + + "equest\022)\n\014attribute_id\030\001 \001(\tB\006\272H\003\310\001\001R\013at" + + "tributeId\022-\n\005state\030\002 \001(\0162\027.common.Active" + + "StateEnumR\005state\"O\n\033ListAttributeValuesR" + + "esponse\0220\n\006values\030\001 \003(\0132\030.policy.attribu" + + "tes.ValueR\006values\"\265\001\n\033CreateAttributeVal" + + "ueRequest\022)\n\014attribute_id\030\001 \001(\tB\006\272H\003\310\001\001R" + + "\013attributeId\022\034\n\005value\030\002 \001(\tB\006\272H\003\310\001\001R\005val" + + "ue\022\030\n\007members\030\003 \003(\tR\007members\0223\n\010metadata" + + "\030d \001(\0132\027.common.MetadataMutableR\010metadat" + + "a\"N\n\034CreateAttributeValueResponse\022.\n\005val" + + "ue\030\001 \001(\0132\030.policy.attributes.ValueR\005valu" + + "e\"\332\001\n\033UpdateAttributeValueRequest\022\026\n\002id\030" + + "\001 \001(\tB\006\272H\003\310\001\001R\002id\022\030\n\007members\030\004 \003(\tR\007memb" + + "ers\0223\n\010metadata\030d \001(\0132\027.common.MetadataM" + + "utableR\010metadata\022T\n\030metadata_update_beha" + + "vior\030e \001(\0162\032.common.MetadataUpdateEnumR\026" + + "metadataUpdateBehavior\"N\n\034UpdateAttribut" + + "eValueResponse\022.\n\005value\030\001 \001(\0132\030.policy.a" + + "ttributes.ValueR\005value\"9\n\037DeactivateAttr" + + "ibuteValueRequest\022\026\n\002id\030\001 \001(\tB\006\272H\003\310\001\001R\002i" + + "d\"R\n DeactivateAttributeValueResponse\022.\n" + + "\005value\030\001 \001(\0132\030.policy.attributes.ValueR\005" + + "value\"\225\001\n\'AssignKeyAccessServerToAttribu" + + "teRequest\022j\n\033attribute_key_access_server" + + "\030\001 \001(\0132+.policy.attributes.AttributeKeyA" + + "ccessServerR\030attributeKeyAccessServer\"\226\001" + + "\n(AssignKeyAccessServerToAttributeRespon" + + "se\022j\n\033attribute_key_access_server\030\001 \001(\0132" + + "+.policy.attributes.AttributeKeyAccessSe" + + "rverR\030attributeKeyAccessServer\"\227\001\n)Remov" + + "eKeyAccessServerFromAttributeRequest\022j\n\033" + + "attribute_key_access_server\030\001 \001(\0132+.poli" + + "cy.attributes.AttributeKeyAccessServerR\030" + + "attributeKeyAccessServer\"\230\001\n*RemoveKeyAc" + + "cessServerFromAttributeResponse\022j\n\033attri" + + "bute_key_access_server\030\001 \001(\0132+.policy.at" + + "tributes.AttributeKeyAccessServerR\030attri" + + "buteKeyAccessServer\"\205\001\n#AssignKeyAccessS" + + "erverToValueRequest\022^\n\027value_key_access_" + + "server\030\001 \001(\0132\'.policy.attributes.ValueKe" + + "yAccessServerR\024valueKeyAccessServer\"\206\001\n$" + + "AssignKeyAccessServerToValueResponse\022^\n\027" + + "value_key_access_server\030\001 \001(\0132\'.policy.a" + + "ttributes.ValueKeyAccessServerR\024valueKey" + + "AccessServer\"\207\001\n%RemoveKeyAccessServerFr" + + "omValueRequest\022^\n\027value_key_access_serve" + + "r\030\001 \001(\0132\'.policy.attributes.ValueKeyAcce" + + "ssServerR\024valueKeyAccessServer\"\210\001\n&Remov" + + "eKeyAccessServerFromValueResponse\022^\n\027val" + "ue_key_access_server\030\001 \001(\0132\'.policy.attr" + "ibutes.ValueKeyAccessServerR\024valueKeyAcc" + - "essServer\"\206\001\n$AssignKeyAccessServerToVal" + - "ueResponse\022^\n\027value_key_access_server\030\001 " + - "\001(\0132\'.policy.attributes.ValueKeyAccessSe" + - "rverR\024valueKeyAccessServer\"\207\001\n%RemoveKey" + - "AccessServerFromValueRequest\022^\n\027value_ke" + - "y_access_server\030\001 \001(\0132\'.policy.attribute" + - "s.ValueKeyAccessServerR\024valueKeyAccessSe" + - "rver\"\210\001\n&RemoveKeyAccessServerFromValueR" + - "esponse\022^\n\027value_key_access_server\030\001 \001(\013" + - "2\'.policy.attributes.ValueKeyAccessServe" + - "rR\024valueKeyAccessServer*\263\001\n\025AttributeRul" + - "eTypeEnum\022(\n$ATTRIBUTE_RULE_TYPE_ENUM_UN" + - "SPECIFIED\020\000\022#\n\037ATTRIBUTE_RULE_TYPE_ENUM_" + - "ALL_OF\020\001\022#\n\037ATTRIBUTE_RULE_TYPE_ENUM_ANY" + - "_OF\020\002\022&\n\"ATTRIBUTE_RULE_TYPE_ENUM_HIERAR" + - "CHY\020\0032\307\023\n\021AttributesService\022g\n\016ListAttri" + - "butes\022(.policy.attributes.ListAttributes" + - "Request\032).policy.attributes.ListAttribut" + - "esResponse\"\000\022v\n\023ListAttributeValues\022-.po" + - "licy.attributes.ListAttributeValuesReque" + - "st\032..policy.attributes.ListAttributeValu" + - "esResponse\"\000\022y\n\014GetAttribute\022&.policy.at" + - "tributes.GetAttributeRequest\032\'.policy.at" + - "tributes.GetAttributeResponse\"\030\202\323\344\223\002\022\022\020/" + - "attributes/{id}\022\236\001\n\030GetAttributesByValue" + - "Fqns\0222.policy.attributes.GetAttributesBy" + - "ValueFqnsRequest\0323.policy.attributes.Get" + - "AttributesByValueFqnsResponse\"\031\202\323\344\223\002\023\022\021/" + - "attributes/*/fqn\022\200\001\n\017CreateAttribute\022).p" + - "olicy.attributes.CreateAttributeRequest\032" + - "*.policy.attributes.CreateAttributeRespo" + - "nse\"\026\202\323\344\223\002\020\"\013/attributes:\001*\022\205\001\n\017UpdateAt" + - "tribute\022).policy.attributes.UpdateAttrib" + - "uteRequest\032*.policy.attributes.UpdateAtt" + - "ributeResponse\"\033\202\323\344\223\002\0252\020/attributes/{id}" + - ":\001*\022\216\001\n\023DeactivateAttribute\022-.policy.att" + - "ributes.DeactivateAttributeRequest\032..pol" + - "icy.attributes.DeactivateAttributeRespon" + - "se\"\030\202\323\344\223\002\022*\020/attributes/{id}\022\221\001\n\021GetAttr" + - "ibuteValue\022+.policy.attributes.GetAttrib" + - "uteValueRequest\032,.policy.attributes.GetA" + - "ttributeValueResponse\"!\202\323\344\223\002\033\022\031/attribut" + - "es/*/values/{id}\022\245\001\n\024CreateAttributeValu" + - "e\022..policy.attributes.CreateAttributeVal" + - "ueRequest\032/.policy.attributes.CreateAttr" + - "ibuteValueResponse\",\202\323\344\223\002&\"!/attributes/" + - "{attribute_id}/values:\001*\022\235\001\n\024UpdateAttri" + - "buteValue\022..policy.attributes.UpdateAttr" + - "ibuteValueRequest\032/.policy.attributes.Up" + - "dateAttributeValueResponse\"$\202\323\344\223\002\0362\031/att" + - "ributes/*/values/{id}:\001*\022\246\001\n\030DeactivateA" + - "ttributeValue\0222.policy.attributes.Deacti" + - "vateAttributeValueRequest\0323.policy.attri" + - "butes.DeactivateAttributeValueResponse\"!" + - "\202\323\344\223\002\033*\031/attributes/*/values/{id}\022\344\001\n As" + - "signKeyAccessServerToAttribute\022:.policy." + - "attributes.AssignKeyAccessServerToAttrib" + - "uteRequest\032;.policy.attributes.AssignKey" + - "AccessServerToAttributeResponse\"G\202\323\344\223\002A\"" + - "\"/attributes/keyaccessserver/assign:\033att" + - "ribute_key_access_server\022\352\001\n\"RemoveKeyAc" + - "cessServerFromAttribute\022<.policy.attribu" + - "tes.RemoveKeyAccessServerFromAttributeRe" + - "quest\032=.policy.attributes.RemoveKeyAcces" + - "sServerFromAttributeResponse\"G\202\323\344\223\002A\"\"/a" + - "ttributes/keyaccessserver/remove:\033attrib" + - "ute_key_access_server\022\333\001\n\034AssignKeyAcces" + - "sServerToValue\0226.policy.attributes.Assig" + - "nKeyAccessServerToValueRequest\0327.policy." + - "attributes.AssignKeyAccessServerToValueR" + - "esponse\"J\202\323\344\223\002D\")/attributes/values/keya" + - "ccessserver/assign:\027value_key_access_ser" + - "ver\022\341\001\n\036RemoveKeyAccessServerFromValue\0228" + - ".policy.attributes.RemoveKeyAccessServer" + - "FromValueRequest\0329.policy.attributes.Rem" + - "oveKeyAccessServerFromValueResponse\"J\202\323\344" + - "\223\002D\")/attributes/values/keyaccessserver/" + - "remove:\027value_key_access_serverB\330\001\n%io.o" + - "pentdf.platform.policy.attributesB\017Attri" + - "butesProtoP\001Z9github.com/opentdf/platfor" + - "m/protocol/go/policy/attributes\242\002\003PAX\252\002\021" + - "Policy.Attributes\312\002\021Policy\\Attributes\342\002\035" + - "Policy\\Attributes\\GPBMetadata\352\002\022Policy::" + - "Attributesb\006proto3" + "essServer*\263\001\n\025AttributeRuleTypeEnum\022(\n$A" + + "TTRIBUTE_RULE_TYPE_ENUM_UNSPECIFIED\020\000\022#\n" + + "\037ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF\020\001\022#\n\037AT" + + "TRIBUTE_RULE_TYPE_ENUM_ANY_OF\020\002\022&\n\"ATTRI" + + "BUTE_RULE_TYPE_ENUM_HIERARCHY\020\0032\307\023\n\021Attr" + + "ibutesService\022g\n\016ListAttributes\022(.policy" + + ".attributes.ListAttributesRequest\032).poli" + + "cy.attributes.ListAttributesResponse\"\000\022v" + + "\n\023ListAttributeValues\022-.policy.attribute" + + "s.ListAttributeValuesRequest\032..policy.at" + + "tributes.ListAttributeValuesResponse\"\000\022y" + + "\n\014GetAttribute\022&.policy.attributes.GetAt" + + "tributeRequest\032\'.policy.attributes.GetAt" + + "tributeResponse\"\030\202\323\344\223\002\022\022\020/attributes/{id" + + "}\022\236\001\n\030GetAttributesByValueFqns\0222.policy." + + "attributes.GetAttributesByValueFqnsReque" + + "st\0323.policy.attributes.GetAttributesByVa" + + "lueFqnsResponse\"\031\202\323\344\223\002\023\022\021/attributes/*/f" + + "qn\022\200\001\n\017CreateAttribute\022).policy.attribut" + + "es.CreateAttributeRequest\032*.policy.attri" + + "butes.CreateAttributeResponse\"\026\202\323\344\223\002\020\"\013/" + + "attributes:\001*\022\205\001\n\017UpdateAttribute\022).poli" + + "cy.attributes.UpdateAttributeRequest\032*.p" + + "olicy.attributes.UpdateAttributeResponse" + + "\"\033\202\323\344\223\002\0252\020/attributes/{id}:\001*\022\216\001\n\023Deacti" + + "vateAttribute\022-.policy.attributes.Deacti" + + "vateAttributeRequest\032..policy.attributes" + + ".DeactivateAttributeResponse\"\030\202\323\344\223\002\022*\020/a" + + "ttributes/{id}\022\221\001\n\021GetAttributeValue\022+.p" + + "olicy.attributes.GetAttributeValueReques" + + "t\032,.policy.attributes.GetAttributeValueR" + + "esponse\"!\202\323\344\223\002\033\022\031/attributes/*/values/{i" + + "d}\022\245\001\n\024CreateAttributeValue\022..policy.att" + + "ributes.CreateAttributeValueRequest\032/.po" + + "licy.attributes.CreateAttributeValueResp" + + "onse\",\202\323\344\223\002&\"!/attributes/{attribute_id}" + + "/values:\001*\022\235\001\n\024UpdateAttributeValue\022..po" + + "licy.attributes.UpdateAttributeValueRequ" + + "est\032/.policy.attributes.UpdateAttributeV" + + "alueResponse\"$\202\323\344\223\002\0362\031/attributes/*/valu" + + "es/{id}:\001*\022\246\001\n\030DeactivateAttributeValue\022" + + "2.policy.attributes.DeactivateAttributeV" + + "alueRequest\0323.policy.attributes.Deactiva" + + "teAttributeValueResponse\"!\202\323\344\223\002\033*\031/attri" + + "butes/*/values/{id}\022\344\001\n AssignKeyAccessS" + + "erverToAttribute\022:.policy.attributes.Ass" + + "ignKeyAccessServerToAttributeRequest\032;.p" + + "olicy.attributes.AssignKeyAccessServerTo" + + "AttributeResponse\"G\202\323\344\223\002A\"\"/attributes/k" + + "eyaccessserver/assign:\033attribute_key_acc" + + "ess_server\022\352\001\n\"RemoveKeyAccessServerFrom" + + "Attribute\022<.policy.attributes.RemoveKeyA" + + "ccessServerFromAttributeRequest\032=.policy" + + ".attributes.RemoveKeyAccessServerFromAtt" + + "ributeResponse\"G\202\323\344\223\002A\"\"/attributes/keya" + + "ccessserver/remove:\033attribute_key_access" + + "_server\022\333\001\n\034AssignKeyAccessServerToValue" + + "\0226.policy.attributes.AssignKeyAccessServ" + + "erToValueRequest\0327.policy.attributes.Ass" + + "ignKeyAccessServerToValueResponse\"J\202\323\344\223\002" + + "D\")/attributes/values/keyaccessserver/as" + + "sign:\027value_key_access_server\022\341\001\n\036Remove" + + "KeyAccessServerFromValue\0228.policy.attrib" + + "utes.RemoveKeyAccessServerFromValueReque" + + "st\0329.policy.attributes.RemoveKeyAccessSe" + + "rverFromValueResponse\"J\202\323\344\223\002D\")/attribut" + + "es/values/keyaccessserver/remove:\027value_" + + "key_access_serverB\330\001\n%io.opentdf.platfor" + + "m.policy.attributesB\017AttributesProtoP\001Z9" + + "github.com/opentdf/platform/protocol/go/" + + "policy/attributes\242\002\003PAX\252\002\021Policy.Attribu" + + "tes\312\002\021Policy\\Attributes\342\002\035Policy\\Attribu" + + "tes\\GPBMetadata\352\002\022Policy::Attributesb\006pr" + + "oto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, diff --git a/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/Value.java b/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/Value.java index cff6145299..7d1411e9d4 100644 --- a/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/Value.java +++ b/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/Value.java @@ -19,8 +19,7 @@ private Value(com.google.protobuf.GeneratedMessageV3.Builder builder) { private Value() { id_ = ""; value_ = ""; - members_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + members_ = java.util.Collections.emptyList(); grants_ = java.util.Collections.emptyList(); fqn_ = ""; } @@ -160,18 +159,28 @@ public java.lang.String getValue() { public static final int MEMBERS_FIELD_NUMBER = 4; @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList members_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + private java.util.List members_; /** *
    * list of attribute values that this value is related to (attribute group)
    * 
* - * repeated string members = 4 [json_name = "members"]; - * @return A list containing the members. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public com.google.protobuf.ProtocolStringList - getMembersList() { + @java.lang.Override + public java.util.List getMembersList() { + return members_; + } + /** + *
+   * list of attribute values that this value is related to (attribute group)
+   * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + @java.lang.Override + public java.util.List + getMembersOrBuilderList() { return members_; } /** @@ -179,9 +188,9 @@ public java.lang.String getValue() { * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @return The count of members. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ + @java.lang.Override public int getMembersCount() { return members_.size(); } @@ -190,11 +199,10 @@ public int getMembersCount() { * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @param index The index of the element to return. - * @return The members at the given index. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public java.lang.String getMembers(int index) { + @java.lang.Override + public io.opentdf.platform.policy.attributes.Value getMembers(int index) { return members_.get(index); } /** @@ -202,13 +210,12 @@ public java.lang.String getMembers(int index) { * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @param index The index of the value to return. - * @return The bytes of the members at the given index. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public com.google.protobuf.ByteString - getMembersBytes(int index) { - return members_.getByteString(index); + @java.lang.Override + public io.opentdf.platform.policy.attributes.ValueOrBuilder getMembersOrBuilder( + int index) { + return members_.get(index); } public static final int GRANTS_FIELD_NUMBER = 5; @@ -411,7 +418,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) com.google.protobuf.GeneratedMessageV3.writeString(output, 3, value_); } for (int i = 0; i < members_.size(); i++) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 4, members_.getRaw(i)); + output.writeMessage(4, members_.get(i)); } for (int i = 0; i < grants_.size(); i++) { output.writeMessage(5, grants_.get(i)); @@ -444,13 +451,9 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(value_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, value_); } - { - int dataSize = 0; - for (int i = 0; i < members_.size(); i++) { - dataSize += computeStringSizeNoTag(members_.getRaw(i)); - } - size += dataSize; - size += 1 * getMembersList().size(); + for (int i = 0; i < members_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, members_.get(i)); } for (int i = 0; i < grants_.size(); i++) { size += com.google.protobuf.CodedOutputStream @@ -675,6 +678,7 @@ private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessageV3 .alwaysUseFieldBuilders) { getAttributeFieldBuilder(); + getMembersFieldBuilder(); getGrantsFieldBuilder(); getActiveFieldBuilder(); getMetadataFieldBuilder(); @@ -691,8 +695,13 @@ public Builder clear() { attributeBuilder_ = null; } value_ = ""; - members_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + if (membersBuilder_ == null) { + members_ = java.util.Collections.emptyList(); + } else { + members_ = null; + membersBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); if (grantsBuilder_ == null) { grants_ = java.util.Collections.emptyList(); } else { @@ -744,6 +753,15 @@ public io.opentdf.platform.policy.attributes.Value buildPartial() { } private void buildPartialRepeatedFields(io.opentdf.platform.policy.attributes.Value result) { + if (membersBuilder_ == null) { + if (((bitField0_ & 0x00000008) != 0)) { + members_ = java.util.Collections.unmodifiableList(members_); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.members_ = members_; + } else { + result.members_ = membersBuilder_.build(); + } if (grantsBuilder_ == null) { if (((bitField0_ & 0x00000010) != 0)) { grants_ = java.util.Collections.unmodifiableList(grants_); @@ -770,10 +788,6 @@ private void buildPartial0(io.opentdf.platform.policy.attributes.Value result) { if (((from_bitField0_ & 0x00000004) != 0)) { result.value_ = value_; } - if (((from_bitField0_ & 0x00000008) != 0)) { - members_.makeImmutable(); - result.members_ = members_; - } if (((from_bitField0_ & 0x00000020) != 0)) { result.fqn_ = fqn_; } @@ -849,15 +863,31 @@ public Builder mergeFrom(io.opentdf.platform.policy.attributes.Value other) { bitField0_ |= 0x00000004; onChanged(); } - if (!other.members_.isEmpty()) { - if (members_.isEmpty()) { - members_ = other.members_; - bitField0_ |= 0x00000008; - } else { - ensureMembersIsMutable(); - members_.addAll(other.members_); + if (membersBuilder_ == null) { + if (!other.members_.isEmpty()) { + if (members_.isEmpty()) { + members_ = other.members_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensureMembersIsMutable(); + members_.addAll(other.members_); + } + onChanged(); + } + } else { + if (!other.members_.isEmpty()) { + if (membersBuilder_.isEmpty()) { + membersBuilder_.dispose(); + membersBuilder_ = null; + members_ = other.members_; + bitField0_ = (bitField0_ & ~0x00000008); + membersBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getMembersFieldBuilder() : null; + } else { + membersBuilder_.addAllMessages(other.members_); + } } - onChanged(); } if (grantsBuilder_ == null) { if (!other.grants_.isEmpty()) { @@ -940,9 +970,16 @@ public Builder mergeFrom( break; } // case 26 case 34: { - java.lang.String s = input.readStringRequireUtf8(); - ensureMembersIsMutable(); - members_.add(s); + io.opentdf.platform.policy.attributes.Value m = + input.readMessage( + io.opentdf.platform.policy.attributes.Value.parser(), + extensionRegistry); + if (membersBuilder_ == null) { + ensureMembersIsMutable(); + members_.add(m); + } else { + membersBuilder_.addMessage(m); + } break; } // case 34 case 42: { @@ -1279,80 +1316,97 @@ public Builder setValueBytes( return this; } - private com.google.protobuf.LazyStringArrayList members_ = - com.google.protobuf.LazyStringArrayList.emptyList(); + private java.util.List members_ = + java.util.Collections.emptyList(); private void ensureMembersIsMutable() { - if (!members_.isModifiable()) { - members_ = new com.google.protobuf.LazyStringArrayList(members_); - } - bitField0_ |= 0x00000008; + if (!((bitField0_ & 0x00000008) != 0)) { + members_ = new java.util.ArrayList(members_); + bitField0_ |= 0x00000008; + } } + + private com.google.protobuf.RepeatedFieldBuilderV3< + io.opentdf.platform.policy.attributes.Value, io.opentdf.platform.policy.attributes.Value.Builder, io.opentdf.platform.policy.attributes.ValueOrBuilder> membersBuilder_; + /** *
      * list of attribute values that this value is related to (attribute group)
      * 
* - * repeated string members = 4 [json_name = "members"]; - * @return A list containing the members. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public com.google.protobuf.ProtocolStringList - getMembersList() { - members_.makeImmutable(); - return members_; + public java.util.List getMembersList() { + if (membersBuilder_ == null) { + return java.util.Collections.unmodifiableList(members_); + } else { + return membersBuilder_.getMessageList(); + } } /** *
      * list of attribute values that this value is related to (attribute group)
      * 
* - * repeated string members = 4 [json_name = "members"]; - * @return The count of members. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ public int getMembersCount() { - return members_.size(); + if (membersBuilder_ == null) { + return members_.size(); + } else { + return membersBuilder_.getCount(); + } } /** *
      * list of attribute values that this value is related to (attribute group)
      * 
* - * repeated string members = 4 [json_name = "members"]; - * @param index The index of the element to return. - * @return The members at the given index. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public java.lang.String getMembers(int index) { - return members_.get(index); + public io.opentdf.platform.policy.attributes.Value getMembers(int index) { + if (membersBuilder_ == null) { + return members_.get(index); + } else { + return membersBuilder_.getMessage(index); + } } /** *
      * list of attribute values that this value is related to (attribute group)
      * 
* - * repeated string members = 4 [json_name = "members"]; - * @param index The index of the value to return. - * @return The bytes of the members at the given index. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public com.google.protobuf.ByteString - getMembersBytes(int index) { - return members_.getByteString(index); + public Builder setMembers( + int index, io.opentdf.platform.policy.attributes.Value value) { + if (membersBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMembersIsMutable(); + members_.set(index, value); + onChanged(); + } else { + membersBuilder_.setMessage(index, value); + } + return this; } /** *
      * list of attribute values that this value is related to (attribute group)
      * 
* - * repeated string members = 4 [json_name = "members"]; - * @param index The index to set the value at. - * @param value The members to set. - * @return This builder for chaining. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ public Builder setMembers( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureMembersIsMutable(); - members_.set(index, value); - bitField0_ |= 0x00000008; - onChanged(); + int index, io.opentdf.platform.policy.attributes.Value.Builder builderForValue) { + if (membersBuilder_ == null) { + ensureMembersIsMutable(); + members_.set(index, builderForValue.build()); + onChanged(); + } else { + membersBuilder_.setMessage(index, builderForValue.build()); + } return this; } /** @@ -1360,17 +1414,40 @@ public Builder setMembers( * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @param value The members to add. - * @return This builder for chaining. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public Builder addMembers(io.opentdf.platform.policy.attributes.Value value) { + if (membersBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMembersIsMutable(); + members_.add(value); + onChanged(); + } else { + membersBuilder_.addMessage(value); + } + return this; + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ public Builder addMembers( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureMembersIsMutable(); - members_.add(value); - bitField0_ |= 0x00000008; - onChanged(); + int index, io.opentdf.platform.policy.attributes.Value value) { + if (membersBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMembersIsMutable(); + members_.add(index, value); + onChanged(); + } else { + membersBuilder_.addMessage(index, value); + } return this; } /** @@ -1378,17 +1455,54 @@ public Builder addMembers( * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @param values The members to add. - * @return This builder for chaining. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public Builder addMembers( + io.opentdf.platform.policy.attributes.Value.Builder builderForValue) { + if (membersBuilder_ == null) { + ensureMembersIsMutable(); + members_.add(builderForValue.build()); + onChanged(); + } else { + membersBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public Builder addMembers( + int index, io.opentdf.platform.policy.attributes.Value.Builder builderForValue) { + if (membersBuilder_ == null) { + ensureMembersIsMutable(); + members_.add(index, builderForValue.build()); + onChanged(); + } else { + membersBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ public Builder addAllMembers( - java.lang.Iterable values) { - ensureMembersIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, members_); - bitField0_ |= 0x00000008; - onChanged(); + java.lang.Iterable values) { + if (membersBuilder_ == null) { + ensureMembersIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, members_); + onChanged(); + } else { + membersBuilder_.addAllMessages(values); + } return this; } /** @@ -1396,14 +1510,16 @@ public Builder addAllMembers( * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @return This builder for chaining. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ public Builder clearMembers() { - members_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008);; - onChanged(); + if (membersBuilder_ == null) { + members_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + } else { + membersBuilder_.clear(); + } return this; } /** @@ -1411,20 +1527,106 @@ public Builder clearMembers() { * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @param value The bytes of the members to add. - * @return This builder for chaining. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - public Builder addMembersBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureMembersIsMutable(); - members_.add(value); - bitField0_ |= 0x00000008; - onChanged(); + public Builder removeMembers(int index) { + if (membersBuilder_ == null) { + ensureMembersIsMutable(); + members_.remove(index); + onChanged(); + } else { + membersBuilder_.remove(index); + } return this; } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public io.opentdf.platform.policy.attributes.Value.Builder getMembersBuilder( + int index) { + return getMembersFieldBuilder().getBuilder(index); + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public io.opentdf.platform.policy.attributes.ValueOrBuilder getMembersOrBuilder( + int index) { + if (membersBuilder_ == null) { + return members_.get(index); } else { + return membersBuilder_.getMessageOrBuilder(index); + } + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public java.util.List + getMembersOrBuilderList() { + if (membersBuilder_ != null) { + return membersBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(members_); + } + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public io.opentdf.platform.policy.attributes.Value.Builder addMembersBuilder() { + return getMembersFieldBuilder().addBuilder( + io.opentdf.platform.policy.attributes.Value.getDefaultInstance()); + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public io.opentdf.platform.policy.attributes.Value.Builder addMembersBuilder( + int index) { + return getMembersFieldBuilder().addBuilder( + index, io.opentdf.platform.policy.attributes.Value.getDefaultInstance()); + } + /** + *
+     * list of attribute values that this value is related to (attribute group)
+     * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + public java.util.List + getMembersBuilderList() { + return getMembersFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + io.opentdf.platform.policy.attributes.Value, io.opentdf.platform.policy.attributes.Value.Builder, io.opentdf.platform.policy.attributes.ValueOrBuilder> + getMembersFieldBuilder() { + if (membersBuilder_ == null) { + membersBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + io.opentdf.platform.policy.attributes.Value, io.opentdf.platform.policy.attributes.Value.Builder, io.opentdf.platform.policy.attributes.ValueOrBuilder>( + members_, + ((bitField0_ & 0x00000008) != 0), + getParentForChildren(), + isClean()); + members_ = null; + } + return membersBuilder_; + } private java.util.List grants_ = java.util.Collections.emptyList(); diff --git a/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/ValueOrBuilder.java b/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/ValueOrBuilder.java index eb6cc3c7b9..22324b46f3 100644 --- a/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/ValueOrBuilder.java +++ b/sdkjava/src/main/java/io/opentdf/platform/policy/attributes/ValueOrBuilder.java @@ -60,18 +60,24 @@ public interface ValueOrBuilder extends * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @return A list containing the members. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - java.util.List + java.util.List getMembersList(); /** *
    * list of attribute values that this value is related to (attribute group)
    * 
* - * repeated string members = 4 [json_name = "members"]; - * @return The count of members. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; + */ + io.opentdf.platform.policy.attributes.Value getMembers(int index); + /** + *
+   * list of attribute values that this value is related to (attribute group)
+   * 
+ * + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ int getMembersCount(); /** @@ -79,22 +85,19 @@ public interface ValueOrBuilder extends * list of attribute values that this value is related to (attribute group) * * - * repeated string members = 4 [json_name = "members"]; - * @param index The index of the element to return. - * @return The members at the given index. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - java.lang.String getMembers(int index); + java.util.List + getMembersOrBuilderList(); /** *
    * list of attribute values that this value is related to (attribute group)
    * 
* - * repeated string members = 4 [json_name = "members"]; - * @param index The index of the value to return. - * @return The bytes of the members at the given index. + * repeated .policy.attributes.Value members = 4 [json_name = "members"]; */ - com.google.protobuf.ByteString - getMembersBytes(int index); + io.opentdf.platform.policy.attributes.ValueOrBuilder getMembersOrBuilder( + int index); /** *
diff --git a/services/policy/attributes/attributes.proto b/services/policy/attributes/attributes.proto
index 808875e6fd..c07e33f0a8 100644
--- a/services/policy/attributes/attributes.proto
+++ b/services/policy/attributes/attributes.proto
@@ -54,7 +54,7 @@ message Value {
   string value = 3;
 
   // list of attribute values that this value is related to (attribute group)
-  repeated string members = 4;
+  repeated Value members = 4;
 
   // list of key access servers
   repeated kasregistry.KeyAccessServer grants = 5;
diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 47e0e2344b..02806df563 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -8,6 +8,7 @@ import (
 	sq "github.com/Masterminds/squirrel"
 	"github.com/jackc/pgx/v5"
 	"github.com/opentdf/platform/internal/db"
+	"github.com/opentdf/platform/internal/set"
 	"github.com/opentdf/platform/protocol/go/common"
 	"github.com/opentdf/platform/protocol/go/policy/attributes"
 	"google.golang.org/protobuf/encoding/protojson"
@@ -19,31 +20,126 @@ type attributeValueSelectOptions struct {
 	state   string
 }
 
-func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*attributes.Value, error) {
+func getMembersFromStringArray(c PolicyDbClient, members []string) ([]*attributes.Value, error) {
+	// Hydrate members
+	hydratedMemberIds := set.NewSet()
+	var hydratedMembers []*attributes.Value
+
+	for _, member := range members {
+		var (
+			vm_id     string
+			value_id  string
+			member_id string
+		)
+
+		// Get member value from db
+		sql, args, err := getMemberSql(member)
+		if err != nil {
+			return nil, err
+		}
+		if r, err := c.QueryRow(context.TODO(), sql, args, err); err != nil {
+			return nil, err
+		} else if err := r.Scan(&vm_id, &value_id, &member_id); err != nil {
+			return nil, db.WrapIfKnownInvalidQueryErr(err)
+		}
+		attr, err := c.GetAttributeValue(context.TODO(), member_id)
+		if err != nil {
+			return nil, err
+		}
+
+		if hydratedMemberIds.Contains(member_id) {
+			slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
+			continue
+		}
+
+		hydratedMemberIds.Add(member_id)
+		hydratedMembers = append(hydratedMembers, attr)
+	}
+	return hydratedMembers, nil
+}
+
+func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValueSelectOptions) (*attributes.Value, error) {
 	var (
 		id           string
 		value        string
 		active       bool
-		members      []string
+		membersJson  []byte
 		metadataJson []byte
 		attributeId  string
 		fqn          sql.NullString
+		memberUUIDs  []string
+		members      []*attributes.Value
 	)
-
 	fields := []interface{}{
 		&id,
 		&value,
 		&active,
-		&members,
+		&membersJson,
 		&metadataJson,
 		&attributeId,
 	}
+
 	if opts.withFqn {
 		fields = append(fields, &fqn)
 	}
-
+	println("fqn", fqn.String)
 	if err := row.Scan(fields...); err != nil {
-		return nil, db.WrapIfKnownInvalidQueryErr(err)
+		fields := []interface{}{
+			&id,
+			&value,
+			&active,
+			&memberUUIDs,
+			&metadataJson,
+			&attributeId,
+		}
+		if opts.withFqn {
+			fields = append(fields, &fqn)
+		}
+
+		if err := row.Scan(fields...); err != nil {
+			return nil, db.WrapIfKnownInvalidQueryErr(err)
+		}
+		members, err = getMembersFromStringArray(c, memberUUIDs)
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		// for _, memberJson := range membersJson {
+		// 	// memberJson = memberJson.(json.RawMessage)
+		// 	println("memberJson", string(memberJson))
+		// 	// var i interface{}
+		// 	// if err := json.Unmarshal(memberJson, &i); err != nil {
+		// 	// 	return nil, err
+		// 	// }
+		// 	// memberattributesValuesProtojson(membersJson)
+
+		// 	member, err := attributesValuesProtojson(c, memberJson)
+		// 	if err != nil {
+		// 		return nil, err
+		// 	}
+		// 	// member := &attributes.Value{}
+		// 	// if err := protojson.Unmarshal(memberJson, member); err != nil {
+		// 	// 	return nil, err
+		// 	// }
+		// 	members = append(members, member)
+		// }
+		println("membersJson before", string(membersJson))
+		if membersJson != nil {
+			members, err = attributesValuesProtojson(c, membersJson)
+			println("len(members)", len(members))
+			for _, member := range members {
+				println("member", member.Id)
+			}
+			// if len(members) == 0 {
+			// 	// log.Fatal("members is empty")
+			// 	println("members is empty")
+			// }
+			// log.Fatal("IsSuE In UnMaRsHaLlInG")
+			if err != nil {
+				println("IsSuE In UnMaRsHaLlInG")
+				return nil, err
+			}
+		}
 	}
 
 	m := &common.Metadata{}
@@ -52,6 +148,46 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 			return nil, err
 		}
 	}
+	println("fqn: ", fqn.String)
+
+	// // Hydrate members
+	// hydratedMemberIds := set.NewSet()
+	// var hydratedMembers []*attributes.Value
+
+	// for _, member := range members {
+	// 	var (
+	// 		vm_id     string
+	// 		value_id  string
+	// 		member_id string
+	// 	)
+
+	// 	// Get member value from db
+	// 	sql, args, err := getMemberSql(member)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+	// 	if r, err := c.QueryRow(context.TODO(), sql, args, err); err != nil {
+	// 		return nil, err
+	// 	} else if err := r.Scan(&vm_id, &value_id, &member_id); err != nil {
+	// 		return nil, db.WrapIfKnownInvalidQueryErr(err)
+	// 	}
+	// 	attr, err := c.GetAttributeValue(context.TODO(), member_id)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+
+	// 	if hydratedMemberIds.Contains(member_id) {
+	// 		slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
+	// 		continue
+	// 	}
+
+	// 	hydratedMemberIds.Add(member_id)
+	// 	hydratedMembers = append(hydratedMembers, attr)
+	// }
+	// hydratedMembers, err := getMembersFromStringArray(c, memberUUIDs)
+	// if err != nil {
+	// 	return nil, err
+	// }
 
 	v := &attributes.Value{
 		Id:       id,
@@ -59,16 +195,15 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 		Active:   &wrapperspb.BoolValue{Value: active},
 		Members:  members,
 		Metadata: m,
-		// TODO: get & hydrate full attribute
-		Fqn: fqn.String,
+		Fqn:      fqn.String,
 	}
 	return v, nil
 }
 
-func attributeValueHydrateItems(rows pgx.Rows, opts attributeValueSelectOptions) ([]*attributes.Value, error) {
+func attributeValueHydrateItems(c PolicyDbClient, rows pgx.Rows, opts attributeValueSelectOptions) ([]*attributes.Value, error) {
 	list := make([]*attributes.Value, 0)
 	for rows.Next() {
-		v, err := attributeValueHydrateItem(rows, opts)
+		v, err := attributeValueHydrateItem(c, rows, opts)
 		if err != nil {
 			return nil, err
 		}
@@ -81,10 +216,37 @@ func attributeValueHydrateItems(rows pgx.Rows, opts attributeValueSelectOptions)
 /// CRUD
 ///
 
+func addMemberSql(value_id string, member_id string) (string, []interface{}, error) {
+	t := Tables.ValueMembers
+	return db.NewStatementBuilder().
+		Insert(t.Name()).
+		Columns(
+			"value_id",
+			"member_id",
+		).
+		Values(
+			value_id,
+			member_id,
+		).
+		Suffix("RETURNING id").
+		ToSql()
+}
+
+func removeMemberSql(value_id string, member_id string) (string, []interface{}, error) {
+	t := Tables.ValueMembers
+	return db.NewStatementBuilder().
+		Delete(t.Name()).
+		Where(sq.Eq{
+			t.Field("value_id"):  value_id,
+			t.Field("member_id"): member_id,
+		}).
+		Suffix("RETURNING id").
+		ToSql()
+}
+
 func createAttributeValueSql(
 	attribute_id string,
 	value string,
-	members []string,
 	metadata []byte,
 ) (string, []interface{}, error) {
 	t := Tables.AttributeValues
@@ -93,13 +255,13 @@ func createAttributeValueSql(
 		Columns(
 			"attribute_definition_id",
 			"value",
-			"members",
+			// "members",
 			"metadata",
 		).
 		Values(
 			attribute_id,
 			value,
-			members,
+			// members,
 			metadata,
 		).
 		Suffix("RETURNING id").
@@ -115,7 +277,7 @@ func (c PolicyDbClient) CreateAttributeValue(ctx context.Context, attributeId st
 	sql, args, err := createAttributeValueSql(
 		attributeId,
 		v.Value,
-		v.Members,
+		// v.Members,
 		metadataJson,
 	)
 	if err != nil {
@@ -129,6 +291,27 @@ func (c PolicyDbClient) CreateAttributeValue(ctx context.Context, attributeId st
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
+	var members []*attributes.Value
+
+	// Add members
+	for _, member := range v.Members {
+		var vm_id string
+		sql, args, err := addMemberSql(id, member)
+		if err != nil {
+			return nil, err
+		}
+		if r, err := c.QueryRow(ctx, sql, args, err); err != nil {
+			return nil, err
+		} else if err := r.Scan(&vm_id); err != nil {
+			return nil, db.WrapIfKnownInvalidQueryErr(err)
+		}
+		attr, err := c.GetAttributeValue(ctx, member)
+		if err != nil {
+			return nil, err
+		}
+		members = append(members, attr)
+	}
+
 	// Update FQN
 	c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueId: id})
 
@@ -136,37 +319,86 @@ func (c PolicyDbClient) CreateAttributeValue(ctx context.Context, attributeId st
 		Id:        id,
 		Attribute: &attributes.Attribute{Id: attributeId},
 		Value:     v.Value,
-		Members:   v.Members,
+		Members:   members,
 		Metadata:  metadata,
 		Active:    &wrapperspb.BoolValue{Value: true},
 	}
 	return rV, nil
 }
 
+func getMemberSql(id string) (string, []interface{}, error) {
+	t := Tables.ValueMembers
+	fields := []string{
+		t.Field("id"),
+		t.Field("value_id"),
+		t.Field("member_id"),
+	}
+
+	sb := db.NewStatementBuilder().
+		Select(fields...).
+		From(t.Name())
+
+	return sb.
+		Where(sq.Eq{t.Field("id"): id}).
+		ToSql()
+}
+
 func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string, []interface{}, error) {
 	t := Tables.AttributeValues
+	fqnT := Tables.AttrFqn
+	members := "COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+		"'id', vmv.id, " +
+		"'value', vmv.value, " +
+		"'active', vmv.active, " +
+		"'members', vmv.members || ARRAY[]::UUID[], " +
+		"'metadata', vmv.metadata ," +
+		"'attribute_id', vmv.attribute_definition_id "
+	if opts.withFqn {
+		members += ", 'fqn', " + fqnT.Field("fqn")
+	}
+	members += ")) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members"
 	fields := []string{
-		t.Field("id"),
-		t.Field("value"),
-		t.Field("active"),
-		t.Field("members"),
-		t.Field("metadata"),
-		t.Field("attribute_definition_id"),
+		// t.Field("id"),
+		// t.Field("value"),
+		// t.Field("active"),
+		// t.Field("members"),
+		// t.Field("metadata"),
+		// t.Field("attribute_definition_id"),
+		"av.id",
+		"av.value",
+		"av.active",
+		members,
+		"av.metadata",
+		"av.attribute_definition_id",
 	}
 	if opts.withFqn {
+		// fields = append(fields, "MAX("+fqnT.Field("fqn")+") AS fqn")
 		fields = append(fields, Tables.AttrFqn.Field("fqn"))
 	}
 
 	sb := db.NewStatementBuilder().
 		Select(fields...).
-		From(t.Name())
+		From(t.Name() + " av")
+		// add alias
+
+	// join members
+	sb = sb.LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id")
+
+	// join attribute values
+	sb = sb.JoinClause("FULL OUTER JOIN " + t.Name() + " vmv ON vm.member_id = vmv.id")
 
 	if opts.withFqn {
-		fqnT := Tables.AttrFqn
-		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + t.Field("id"))
+		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + "vmv.id")
+		// sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("attribute_id") + " = " + "vmv.attribute_definition_id")
 	}
 
-	return sb.Where(sq.Eq{t.Field("id"): id}).
+	return sb.Where(sq.Eq{
+		"av.id": id}).
+		GroupBy(
+			"av.id",
+			fqnT.Field("fqn"),
+		).
+		// LeftJoin(t.Name() + " ON " + t.Field("id") + " = " + db.Tables.ValueMembers.Field("member_id")).
 		ToSql()
 }
 
@@ -179,7 +411,7 @@ func (c PolicyDbClient) GetAttributeValue(ctx context.Context, id string) (*attr
 		return nil, err
 	}
 
-	a, err := attributeValueHydrateItem(row, opts)
+	a, err := attributeValueHydrateItem(c, row, opts)
 	if err != nil {
 		slog.Error("error hydrating attribute value", slog.String("id", id), slog.String("sql", sql), slog.String("error", err.Error()))
 		return nil, err
@@ -230,7 +462,7 @@ func (c PolicyDbClient) ListAttributeValues(ctx context.Context, attribute_id st
 		return nil, err
 	}
 	defer rows.Close()
-	return attributeValueHydrateItems(rows, opts)
+	return attributeValueHydrateItems(c, rows, opts)
 }
 
 func listAllAttributeValuesSql(opts attributeValueSelectOptions) (string, []interface{}, error) {
@@ -267,12 +499,12 @@ func (c PolicyDbClient) ListAllAttributeValues(ctx context.Context, state string
 		return nil, err
 	}
 	defer rows.Close()
-	return attributeValueHydrateItems(rows, opts)
+	return attributeValueHydrateItems(c, rows, opts)
 }
 
 func updateAttributeValueSql(
 	id string,
-	members []string,
+	// members []string,
 	metadata []byte,
 ) (string, []interface{}, error) {
 	t := Tables.AttributeValues
@@ -282,9 +514,9 @@ func updateAttributeValueSql(
 		sb = sb.Set("metadata", metadata)
 	}
 
-	if members != nil {
-		sb = sb.Set("members", members)
-	}
+	// if members != nil {
+	// 	sb = sb.Set("members", members)
+	// }
 
 	return sb.Where(sq.Eq{t.Field("id"): id}).ToSql()
 }
@@ -303,7 +535,7 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 
 	sql, args, err := updateAttributeValueSql(
 		r.Id,
-		r.Members,
+		// r.Members,
 		metadataJson,
 	)
 	if db.IsQueryBuilderSetClauseError(err) {
@@ -315,9 +547,57 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 		return nil, err
 	}
 
+	prev, err := c.GetAttributeValue(ctx, r.Id)
+	if err != nil {
+		return nil, err
+	}
+
 	if err := c.Exec(ctx, sql, args); err != nil {
 		return nil, err
 	}
+	prevMembersSet := set.NewSet()
+	for _, member := range prev.Members {
+		prevMembersSet.Add(member.Id)
+	}
+
+	membersSet := set.NewSet()
+	for _, member := range r.Members {
+		membersSet.Add(member)
+	}
+
+	toRemove := prevMembersSet.Difference(membersSet).ToSlice()
+	toAdd := membersSet.Difference(prevMembersSet).ToSlice()
+
+	// Remove members
+	for _, member := range toRemove {
+		sql, args, err := removeMemberSql(r.Id, member.(string))
+		if err != nil {
+			return nil, err
+		}
+		if err := c.Exec(ctx, sql, args); err != nil {
+			return nil, err
+		}
+	}
+
+	// Add members
+	for _, member := range toAdd {
+		sql, args, err := addMemberSql(r.Id, member.(string))
+		if err != nil {
+			return nil, err
+		}
+		if err := c.Exec(ctx, sql, args); err != nil {
+			return nil, err
+		}
+	}
+
+	var members []*attributes.Value
+	for _, member := range r.Members {
+		attr, err := c.GetAttributeValue(ctx, member)
+		if err != nil {
+			return nil, err
+		}
+		members = append(members, attr)
+	}
 
 	// Update FQN
 	c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueId: r.Id})
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index 01eef52579..ff1560eaa4 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -29,21 +29,82 @@ func attributesRuleTypeEnumTransformOut(value string) attributes.AttributeRuleTy
 	return attributes.AttributeRuleTypeEnum(attributes.AttributeRuleTypeEnum_value[AttributeRuleTypeEnumPrefix+value])
 }
 
-func attributesValuesProtojson(valuesJson []byte) ([]*attributes.Value, error) {
+func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*attributes.Value, error) {
+	type AttributeValueDBItem struct {
+		// generated uuid in database
+		Id          string           `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+		Metadata    *common.Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"`
+		AttributeId string           `protobuf:"bytes,3,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"`
+		Value       string           `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
+		// list of attribute values that this value is related to (attribute group)
+		Members []string `protobuf:"bytes,5,rep,name=members,proto3" json:"members,omitempty"`
+		// list of key access servers
+		Grants []*kasregistry.KeyAccessServer `protobuf:"bytes,6,rep,name=grants,proto3" json:"grants,omitempty"`
+		Fqn    string                         `protobuf:"bytes,7,opt,name=fqn,proto3" json:"fqn,omitempty"`
+		Active bool                           `protobuf:"bytes,8,opt,name=active,proto3" json:"active,omitempty"`
+	}
+	var item AttributeValueDBItem
+	if err := json.Unmarshal(r, &item); err != nil {
+		return nil, err
+	}
+	if item.Metadata == nil {
+		item.Metadata = &common.Metadata{}
+	}
+
+	// if item.Active == nil {
+	// 	item.Active = &wrapperspb.BoolValue{Value: true}
+	// }
+
+	var members []*attributes.Value
+	if len(item.Members) > 0 {
+		attr, err := c.GetAttributeValue(context.TODO(), item.Id)
+		if err != nil {
+			return nil, err
+		}
+		return attr, nil
+	}
+	println("r", string(r))
+	return &attributes.Value{
+		Id:       item.Id,
+		Value:    item.Value,
+		Members:  members,
+		Metadata: item.Metadata,
+		Fqn:      item.Fqn,
+		Grants:   item.Grants,
+		Active:   &wrapperspb.BoolValue{Value: item.Active},
+	}, nil
+}
+
+func attributesValuesProtojson(c PolicyDbClient, valuesJson []byte) ([]*attributes.Value, error) {
 	var (
 		raw    []json.RawMessage
 		values []*attributes.Value
 	)
+
+	if valuesJson == nil {
+		return values, nil
+	}
+
 	if err := json.Unmarshal(valuesJson, &raw); err != nil {
 		return nil, err
 	}
 
+	if len(raw) == 0 {
+		return values, nil
+	}
+
+	// log.Fatal("valuesJson", string(valuesJson))
+
 	for _, r := range raw {
-		value := attributes.Value{}
-		if err := protojson.Unmarshal(r, &value); err != nil {
+		println("r", string(r))
+		// if string(r) == "[]" {
+		// 	continue
+		// }
+		value, err := convertJSONToAttrVal(c, r)
+		if err != nil {
 			return nil, err
 		}
-		values = append(values, &value)
+		values = append(values, value)
 	}
 	return values, nil
 }
@@ -139,7 +200,7 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 	return sb.GroupBy(g...)
 }
 
-func attributesHydrateItem(row pgx.Row, opts attributesSelectOptions) (*attributes.Attribute, error) {
+func attributesHydrateItem(c PolicyDbClient, row pgx.Row, opts attributesSelectOptions) (*attributes.Attribute, error) {
 	if opts.withKeyAccessGrants {
 		opts.withAttributeValues = true
 	}
@@ -183,7 +244,7 @@ func attributesHydrateItem(row pgx.Row, opts attributesSelectOptions) (*attribut
 
 	var v []*attributes.Value
 	if valuesJson != nil {
-		v, err = attributesValuesProtojson(valuesJson)
+		v, err = attributesValuesProtojson(c, valuesJson)
 		if err != nil {
 			slog.Error("could not unmarshal values", slog.String("error", err.Error()))
 			return nil, err
@@ -213,10 +274,10 @@ func attributesHydrateItem(row pgx.Row, opts attributesSelectOptions) (*attribut
 	return attr, nil
 }
 
-func attributesHydrateList(rows pgx.Rows, opts attributesSelectOptions) ([]*attributes.Attribute, error) {
+func attributesHydrateList(c PolicyDbClient, rows pgx.Rows, opts attributesSelectOptions) ([]*attributes.Attribute, error) {
 	list := make([]*attributes.Attribute, 0)
 	for rows.Next() {
-		attr, err := attributesHydrateItem(rows, opts)
+		attr, err := attributesHydrateItem(c, rows, opts)
 		if err != nil {
 			return nil, err
 		}
@@ -256,7 +317,7 @@ func (c PolicyDbClient) ListAllAttributes(ctx context.Context, state string) ([]
 	}
 	defer rows.Close()
 
-	list, err := attributesHydrateList(rows, opts)
+	list, err := attributesHydrateList(c, rows, opts)
 	if err != nil {
 		slog.Error("could not hydrate list", slog.String("error", err.Error()))
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -280,7 +341,7 @@ func (c PolicyDbClient) ListAllAttributesWithout(ctx context.Context, state stri
 	}
 	defer rows.Close()
 
-	list, err := attributesHydrateList(rows, opts)
+	list, err := attributesHydrateList(c, rows, opts)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
@@ -307,7 +368,7 @@ func (c PolicyDbClient) GetAttribute(ctx context.Context, id string) (*attribute
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
-	attribute, err := attributesHydrateItem(row, opts)
+	attribute, err := attributesHydrateItem(c, row, opts)
 	if err != nil {
 		slog.Error("could not hydrate item", slog.String("attributeId", id), slog.String("error", err.Error()))
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -340,7 +401,7 @@ func (c PolicyDbClient) GetAttributeByFqn(ctx context.Context, fqn string) (*att
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
-	attribute, err := attributesHydrateItem(row, opts)
+	attribute, err := attributesHydrateItem(c, row, opts)
 	if err != nil {
 		slog.Error("could not hydrate item", slog.String("fqn", fqn), slog.String("error", err.Error()))
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -366,7 +427,7 @@ func (c PolicyDbClient) GetAttributesByNamespace(ctx context.Context, namespaceI
 	}
 	defer rows.Close()
 
-	list, err := attributesHydrateList(rows, opts)
+	list, err := attributesHydrateList(c, rows, opts)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
diff --git a/services/policy/db/policy.go b/services/policy/db/policy.go
index 9c22c2353d..52b8d66d7c 100644
--- a/services/policy/db/policy.go
+++ b/services/policy/db/policy.go
@@ -18,6 +18,7 @@ type PolicyDbClient struct {
 var (
 	TableAttributes                    = "attribute_definitions"
 	TableAttributeValues               = "attribute_values"
+	TableValueMembers                  = "value_members"
 	TableNamespaces                    = "attribute_namespaces"
 	TableAttrFqn                       = "attribute_fqns"
 	TableAttributeKeyAccessGrants      = "attribute_definition_key_access_grants"
@@ -30,6 +31,7 @@ var (
 var Tables struct {
 	Attributes                    db.Table
 	AttributeValues               db.Table
+	ValueMembers                  db.Table
 	Namespaces                    db.Table
 	AttrFqn                       db.Table
 	AttributeKeyAccessGrants      db.Table
@@ -42,6 +44,7 @@ var Tables struct {
 func NewClient(c db.Client) *PolicyDbClient {
 	Tables.Attributes = db.NewTable(TableAttributes)
 	Tables.AttributeValues = db.NewTable(TableAttributeValues)
+	Tables.ValueMembers = db.NewTable(TableValueMembers)
 	Tables.Namespaces = db.NewTable(TableNamespaces)
 	Tables.AttrFqn = db.NewTable(TableAttrFqn)
 	Tables.AttributeKeyAccessGrants = db.NewTable(TableAttributeKeyAccessGrants)
diff --git a/services/policy/db/resource_mapping.go b/services/policy/db/resource_mapping.go
index 94cbf2ddde..5aa6a2718e 100644
--- a/services/policy/db/resource_mapping.go
+++ b/services/policy/db/resource_mapping.go
@@ -14,11 +14,11 @@ import (
 	"google.golang.org/protobuf/encoding/protojson"
 )
 
-func resourceMappingHydrateList(rows pgx.Rows) ([]*resourcemapping.ResourceMapping, error) {
+func resourceMappingHydrateList(c PolicyDbClient, rows pgx.Rows) ([]*resourcemapping.ResourceMapping, error) {
 	var list []*resourcemapping.ResourceMapping
 
 	for rows.Next() {
-		rm, err := resourceMappingHydrateItem(rows)
+		rm, err := resourceMappingHydrateItem(c, rows)
 		if err != nil {
 			return nil, err
 		}
@@ -27,7 +27,7 @@ func resourceMappingHydrateList(rows pgx.Rows) ([]*resourcemapping.ResourceMappi
 	return list, nil
 }
 
-func resourceMappingHydrateItem(row pgx.Row) (*resourcemapping.ResourceMapping, error) {
+func resourceMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*resourcemapping.ResourceMapping, error) {
 	var (
 		id                 string
 		metadataJSON       []byte
@@ -54,7 +54,7 @@ func resourceMappingHydrateItem(row pgx.Row) (*resourcemapping.ResourceMapping,
 		}
 	}
 
-	err = protojson.Unmarshal(attributeValueJSON, attributeValue)
+	attributeValue, err = convertJSONToAttrVal(c, attributeValueJSON)
 	if err != nil {
 		return nil, err
 	}
@@ -157,7 +157,7 @@ func (c PolicyDbClient) GetResourceMapping(ctx context.Context, id string) (*res
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
-	rm, err := resourceMappingHydrateItem(row)
+	rm, err := resourceMappingHydrateItem(c, row)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
@@ -183,7 +183,7 @@ func (c PolicyDbClient) ListResourceMappings(ctx context.Context) ([]*resourcema
 	}
 	defer rows.Close()
 
-	list, err := resourceMappingHydrateList(rows)
+	list, err := resourceMappingHydrateList(c, rows)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}

From 2ee64a634d4c96fa42d26e905c7cdcc89a09cc83 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Mon, 11 Mar 2024 17:20:59 -0400
Subject: [PATCH 02/31] remove commented out file

---
 integration/attribute_fqns_test.go.x    | 227 -------------------
 integration/resource_mappings_test.go.x | 276 ------------------------
 2 files changed, 503 deletions(-)
 delete mode 100644 integration/attribute_fqns_test.go.x
 delete mode 100644 integration/resource_mappings_test.go.x

diff --git a/integration/attribute_fqns_test.go.x b/integration/attribute_fqns_test.go.x
deleted file mode 100644
index 8ab635abe0..0000000000
--- a/integration/attribute_fqns_test.go.x
+++ /dev/null
@@ -1,227 +0,0 @@
-package integration
-
-import (
-	"context"
-	"fmt"
-	"log/slog"
-	"testing"
-
-	"github.com/opentdf/platform/internal/db"
-	"github.com/opentdf/platform/internal/fixtures"
-	"github.com/opentdf/platform/protocol/go/policy/attributes"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/suite"
-)
-
-type AttributeFqnSuite struct {
-	suite.Suite
-	schema string
-	f      fixtures.Fixtures
-	db     fixtures.DBInterface
-	ctx    context.Context
-}
-
-func fqnBuilder(n string, a string, v string) string {
-	fqn := "https://"
-	if n != "" && a != "" && v != "" {
-		return fqn + n + "/attr/" + a + "/value/" + v
-	} else if n != "" && a != "" && v == "" {
-		return fqn + n + "/attr/" + a
-	} else if n != "" && a == "" {
-		return fqn + n
-	} else {
-		panic("Invalid FQN")
-	}
-}
-
-func TestAttributeFqnSuite(t *testing.T) {
-	if testing.Short() {
-		t.Skip("skipping attributes integration tests")
-	}
-	suite.Run(t, new(AttributeFqnSuite))
-}
-
-func (s *AttributeFqnSuite) SetupSuite() {
-	slog.Info("setting up db.AttributeFqn test suite")
-	s.ctx = context.Background()
-	s.schema = "test_opentdf_attribute_fqn"
-	s.db = fixtures.NewDBInterface(*Config)
-	s.f = fixtures.NewFixture(s.db)
-	s.f.Provision()
-}
-
-func (s *AttributeFqnSuite) TearDownSuite() {
-	slog.Info("tearing down db.AttributeFqn test suite")
-	s.f.TearDown()
-}
-
-// Test Create Namespace
-func (s *AttributeFqnSuite) TestCreateNamespace() {
-	name := "test_namespace"
-	id, err := s.db.PolicyClient.CreateNamespace(s.ctx, name)
-	s.NoError(err)
-	// Verify FQN
-	fqn, err := s.db.PolicyClient.GetNamespace(s.ctx, id)
-	s.NoError(err)
-	s.NotEmpty(fqn.Fqn)
-	s.Equal(fqnBuilder(name, "", ""), fqn.Fqn)
-}
-
-// Test Create Attribute
-func (s *AttributeFqnSuite) TestCreateAttribute() {
-	n := s.f.GetNamespaceKey("example.com")
-	name := "test_namespace"
-	a, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.AttributeCreateUpdate{
-		NamespaceId: n.Id,
-		Name:        name,
-		Rule:        attributes.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
-	})
-	s.NoError(err)
-	// Verify FQN
-	fqn, err := s.db.PolicyClient.GetAttribute(s.ctx, a.Id)
-	s.NoError(err)
-	s.NotEmpty(fqn.Fqn)
-	s.Equal(fqnBuilder(n.Name, a.Name, ""), fqn.Fqn)
-}
-
-// Test Create Attribute Value
-func (s *AttributeFqnSuite) TestCreateAttributeValue() {
-	a := s.f.GetAttributeKey("example.com/attr/attr1")
-	n := s.f.GetNamespaceKey("example.com")
-	name := "test_namespace"
-	v, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, a.Id, &attributes.ValueCreateUpdate{
-		Value: name,
-	})
-	s.NoError(err)
-	// Verify FQN
-	fqn, err := s.db.PolicyClient.GetAttributeValue(s.ctx, v.Id)
-	s.NoError(err)
-	s.NotEmpty(fqn.Fqn)
-	s.Equal(fqnBuilder(n.Name, a.Name, v.Value), fqn.Fqn)
-}
-
-// Test Get one attribute by the FQN of one of its values
-func (s *AttributeFqnSuite) TestGetAttributeByFqn_WithAttrValueFqn() {
-	fqnFixtureKey := "example.com/attr/attr1/value/value1"
-	fullFqn := fmt.Sprintf("https://%s", fqnFixtureKey)
-	valueFixture := s.f.GetAttributeValueKey(fqnFixtureKey)
-
-	attr, err := s.db.PolicyClient.GetAttributeByFqn(s.ctx, fullFqn)
-	s.NoError(err)
-
-	// there should be only one value
-	s.Equal(1, len(attr.Values))
-
-	// the value should match the fixture
-	av := attr.Values[0]
-	s.Equal(attr.Id, valueFixture.AttributeDefinitionId)
-	s.Equal(av.Id, valueFixture.Id)
-	s.Equal(av.Value, valueFixture.Value)
-}
-
-// Test Get one attribute by the FQN of the attribute definition
-func (s *AttributeFqnSuite) TestGetAttributeByFqn_WithAttrFqn() {
-	fqnFixtureKey := "example.net/attr/attr1"
-	fullFqn := fmt.Sprintf("https://%s", fqnFixtureKey)
-	attrFixture := s.f.GetAttributeKey(fqnFixtureKey)
-
-	attr, err := s.db.PolicyClient.GetAttributeByFqn(s.ctx, fullFqn)
-	s.NoError(err)
-
-	// the number of values should match the fixture
-	s.Equal(2, len(attr.Values))
-
-	// the attribute should match the fixture
-	s.Equal(attr.Id, attrFixture.Id)
-	s.Equal(attr.Name, attrFixture.Name)
-	s.Equal(attr.Rule.String(), fmt.Sprintf("ATTRIBUTE_RULE_TYPE_ENUM_%s", attrFixture.Rule))
-	s.Equal(attr.Active.Value, attrFixture.Active)
-}
-
-// Test multiple get attributes by multiple fqns
-func (s *AttributeFqnSuite) TestGetAttributesByValueFqns() {
-	namespace := "testing_multiple_fqns.get"
-	attr := "test_attr"
-	value1 := "test_value"
-	value2 := "test_value_2"
-	fqn1 := fqnBuilder(namespace, attr, value1)
-	fqn2 := fqnBuilder(namespace, attr, value2)
-
-	// Create namespace
-	nsId, err := s.db.PolicyClient.CreateNamespace(s.ctx, namespace)
-	assert.NoError(s.T(), err)
-
-	// Create attribute
-	a, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attributes.AttributeCreateUpdate{
-		NamespaceId: nsId,
-		Name:        attr,
-		Rule:        attributes.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF,
-	})
-	assert.NoError(s.T(), err)
-
-	// Create attribute value1
-	v1, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, a.Id, &attributes.ValueCreateUpdate{
-		Value: value1,
-	})
-	assert.NoError(s.T(), err)
-
-	// Get attributes by fqns with a solo value
-	fqns := []string{fqn1}
-	attributeAndValue, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, fqns)
-	assert.NoError(s.T(), err)
-
-	// Verify attribute1 is sole attribute
-	assert.Len(s.T(), attributeAndValue, 1)
-	val, ok := attributeAndValue[fqn1]
-	assert.True(s.T(), ok)
-	assert.Equal(s.T(), a.Id, val.Attribute.Id)
-
-	assert.Equal(s.T(), v1.Id, val.Attribute.Values[0].Id)
-	assert.Equal(s.T(), v1.Value, val.Value.Value)
-
-	assert.Equal(s.T(), v1.Value, val.Attribute.Values[0].Value)
-	assert.Equal(s.T(), v1.Id, val.Value.Id)
-
-	// Create attribute value2
-	v2, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, a.Id, &attributes.ValueCreateUpdate{
-		Value: value2,
-	})
-	assert.NoError(s.T(), err)
-
-	// Get attributes by fqns with two values
-	fqns = []string{fqn1, fqn2}
-	attributeAndValue, err = s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, fqns)
-	assert.NoError(s.T(), err)
-	assert.Len(s.T(), attributeAndValue, 2)
-
-	val, ok = attributeAndValue[fqn2]
-	assert.True(s.T(), ok)
-	assert.Equal(s.T(), a.Id, val.Attribute.Id)
-
-	for _, v := range val.Attribute.Values {
-		if v.Id == v1.Id {
-			assert.Equal(s.T(), v1.Id, v.Id)
-			assert.Equal(s.T(), v1.Value, v.Value)
-		} else if v.Id == v2.Id {
-			assert.Equal(s.T(), v2.Id, v.Id)
-			assert.Equal(s.T(), v2.Value, v.Value)
-		} else {
-			assert.Fail(s.T(), "unexpected value", v)
-		}
-	}
-}
-
-func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithNonValueFqns() {
-	nsFqn := fqnBuilder("example.com", "", "")
-	attrFqn := fqnBuilder("example.com", "attr1", "")
-	v, err := s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, []string{nsFqn})
-	assert.Error(s.T(), err)
-	assert.Nil(s.T(), v)
-	assert.ErrorIs(s.T(), err, db.ErrFqnMissingValue)
-
-	v, err = s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, []string{attrFqn})
-	assert.Error(s.T(), err)
-	assert.Nil(s.T(), v)
-	assert.ErrorIs(s.T(), err, db.ErrFqnMissingValue)
-}
diff --git a/integration/resource_mappings_test.go.x b/integration/resource_mappings_test.go.x
deleted file mode 100644
index ab5705391f..0000000000
--- a/integration/resource_mappings_test.go.x
+++ /dev/null
@@ -1,276 +0,0 @@
-package integration
-
-import (
-	"context"
-	"fmt"
-	"log/slog"
-	"testing"
-
-	"github.com/opentdf/platform/internal/db"
-	"github.com/opentdf/platform/internal/fixtures"
-	"github.com/opentdf/platform/protocol/go/common"
-	resourcemapping "github.com/opentdf/platform/protocol/go/policy/resourcemapping"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/suite"
-)
-
-var nonExistentResourceMappingUUID = "45674556-8888-9999-9999-000001230000"
-
-type ResourceMappingsSuite struct {
-	suite.Suite
-	schema string
-	f      fixtures.Fixtures
-	db     fixtures.DBInterface
-	ctx    context.Context
-}
-
-func (s *ResourceMappingsSuite) SetupSuite() {
-	slog.Info("setting up db.ResourceMappings test suite")
-	s.ctx = context.Background()
-	s.schema = "test_opentdf_resource_mappings"
-	s.db = fixtures.NewDBInterface(*Config)
-	s.f = fixtures.NewFixture(s.db)
-	s.f.Provision()
-}
-
-func (s *ResourceMappingsSuite) TearDownSuite() {
-	slog.Info("tearing down db.ResourceMappings test suite")
-	s.f.TearDown()
-}
-
-func (s *ResourceMappingsSuite) getResourceMappingFixtures() []fixtures.FixtureDataResourceMapping {
-	return []fixtures.FixtureDataResourceMapping{
-		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value1"),
-		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value2"),
-		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value3"),
-	}
-}
-
-func (s *ResourceMappingsSuite) Test_CreateResourceMapping() {
-	metadata := &common.MetadataMutable{
-		Labels: map[string]string{
-			"name": "this is the test name of my resource mapping",
-		},
-		Description: "test create resource mapping description",
-	}
-
-	attrValue := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Metadata:         metadata,
-		Terms:            []string{"term1", "term2"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-}
-
-func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithUnknownAttributeValueFails() {
-	metadata := &common.MetadataMutable{}
-
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: nonExistentAttributeValueUuid,
-		Metadata:         metadata,
-		Terms:            []string{"term1", "term2"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.NotNil(s.T(), err)
-	assert.Nil(s.T(), createdMapping)
-	assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation)
-}
-
-func (s *ResourceMappingsSuite) Test_CreateResourceMappingWithEmptyTermsSucceeds() {
-	metadata := &common.MetadataMutable{}
-
-	attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Metadata:         metadata,
-		Terms:            []string{},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-	assert.NotNil(s.T(), createdMapping.Terms)
-	assert.Equal(s.T(), len(createdMapping.Terms), 0)
-}
-
-func (s *ResourceMappingsSuite) Test_ListResourceMappings() {
-	// make sure we can get all fixtures
-	testData := s.getResourceMappingFixtures()
-	mappings, err := s.db.PolicyClient.ListResourceMappings(s.ctx)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), mappings)
-	for _, testMapping := range testData {
-		found := false
-		for _, mapping := range mappings {
-			if testMapping.Id == mapping.Id {
-				found = true
-				break
-			}
-		}
-		assert.True(s.T(), found, fmt.Sprintf("expected to find mapping %s", testMapping.Id))
-	}
-}
-
-func (s *ResourceMappingsSuite) Test_GetResourceMapping() {
-	// make sure we can get all fixtures
-	testData := s.getResourceMappingFixtures()
-	for _, testMapping := range testData {
-		mapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, testMapping.Id)
-		assert.Nil(s.T(), err)
-		assert.NotNil(s.T(), mapping)
-		assert.Equal(s.T(), testMapping.Id, mapping.Id)
-		assert.Equal(s.T(), testMapping.AttributeValueId, mapping.AttributeValue.Id)
-		assert.Equal(s.T(), testMapping.Terms, mapping.Terms)
-	}
-}
-
-func (s *ResourceMappingsSuite) Test_GetResourceMappingWithUnknownIdFails() {
-	mapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, nonExistentResourceMappingUUID)
-	assert.NotNil(s.T(), err)
-	assert.Nil(s.T(), mapping)
-	assert.ErrorIs(s.T(), err, db.ErrNotFound)
-}
-
-func (s *ResourceMappingsSuite) Test_GetResourceMappingOfCreatedSucceeds() {
-	metadata := &common.MetadataMutable{}
-
-	attrValue := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value2")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Metadata:         metadata,
-		Terms:            []string{"term1", "term2"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-
-	got, err := s.db.PolicyClient.GetResourceMapping(s.ctx, createdMapping.Id)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), mapping)
-	assert.Equal(s.T(), createdMapping.Id, got.Id)
-	assert.Equal(s.T(), createdMapping.AttributeValue.Id, got.AttributeValue.Id)
-	assert.Equal(s.T(), createdMapping.Terms, mapping.Terms)
-}
-
-func (s *ResourceMappingsSuite) Test_UpdateResourceMapping() {
-	metadata := &common.MetadataMutable{
-		Labels: map[string]string{
-			"name": "some test resource mapping name",
-		},
-		Description: "some description",
-	}
-
-	attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Metadata:         metadata,
-		Terms:            []string{"some term", "other term"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-
-	updatedMetadata := &common.MetadataMutable{
-		Labels: map[string]string{
-			"name": "new name",
-		},
-		Description: "new description",
-	}
-
-	// update the created with new metadata and terms
-	updatedMapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: createdMapping.AttributeValue.Id,
-		Metadata:         updatedMetadata,
-		Terms:            []string{"updated term1", "updated term 2"},
-	}
-	updated, err := s.db.PolicyClient.UpdateResourceMapping(s.ctx, createdMapping.Id, updatedMapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), updated)
-
-	// get after update to verify db reflects changes made
-	got, err := s.db.PolicyClient.GetResourceMapping(s.ctx, createdMapping.Id)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), got)
-	assert.Equal(s.T(), createdMapping.Id, got.Id)
-	assert.Equal(s.T(), createdMapping.AttributeValue.Id, got.AttributeValue.Id)
-	assert.Equal(s.T(), updatedMapping.Terms, got.Terms)
-	assert.Equal(s.T(), updatedMetadata.Description, got.Metadata.Description)
-	assert.EqualValues(s.T(), updatedMetadata.Labels, got.Metadata.Labels)
-}
-
-func (s *ResourceMappingsSuite) Test_UpdateResourceMappingWithUnknownIdFails() {
-	attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Terms:            []string{"asdf qwerty"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-
-	// update the created with new metadata and terms
-	updatedMapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: createdMapping.AttributeValue.Id,
-		Terms:            []string{"asdf updated term1"},
-	}
-	updated, err := s.db.PolicyClient.UpdateResourceMapping(s.ctx, nonExistentResourceMappingUUID, updatedMapping)
-	assert.NotNil(s.T(), err)
-	assert.Nil(s.T(), updated)
-	assert.ErrorIs(s.T(), err, db.ErrNotFound)
-}
-
-func (s *ResourceMappingsSuite) Test_UpdateResourceMappingWithUnknownAttributeValueIdFails() {
-	attrValue := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Terms:            []string{"testing"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-
-	// update the created with new metadata and terms
-	updatedMapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: nonExistentAttributeValueUuid,
-		Terms:            []string{"testing-2"},
-	}
-	updated, err := s.db.PolicyClient.UpdateResourceMapping(s.ctx, createdMapping.Id, updatedMapping)
-	assert.NotNil(s.T(), err)
-	assert.Nil(s.T(), updated)
-	assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation)
-}
-
-func (s *ResourceMappingsSuite) Test_DeleteResourceMapping() {
-	attrValue := s.f.GetAttributeValueKey("example.net/attr/attr1/value/value1")
-	mapping := &resourcemapping.ResourceMappingCreateUpdate{
-		AttributeValueId: attrValue.Id,
-		Terms:            []string{"term1", "term2"},
-	}
-	createdMapping, err := s.db.PolicyClient.CreateResourceMapping(s.ctx, mapping)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), createdMapping)
-
-	deleted, err := s.db.PolicyClient.DeleteResourceMapping(s.ctx, createdMapping.Id)
-	assert.Nil(s.T(), err)
-	assert.NotNil(s.T(), deleted)
-
-	deletedMapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, createdMapping.Id)
-	assert.NotNil(s.T(), err)
-	assert.Nil(s.T(), deletedMapping)
-}
-
-func (s *ResourceMappingsSuite) Test_DeleteResourceMappingWithUnknownIdFails() {
-	deleted, err := s.db.PolicyClient.DeleteResourceMapping(s.ctx, nonExistentResourceMappingUUID)
-	assert.NotNil(s.T(), err)
-	assert.Nil(s.T(), deleted)
-	assert.ErrorIs(s.T(), err, db.ErrNotFound)
-}
-
-func TestResourceMappingsSuite(t *testing.T) {
-	if testing.Short() {
-		t.Skip("skipping resource mappings integration tests")
-	}
-	suite.Run(t, new(ResourceMappingsSuite))
-}

From 8ec2b58d43a6c093734b9e704bef579b232316df Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Mon, 11 Mar 2024 17:38:25 -0400
Subject: [PATCH 03/31] fix subject mapping test

---
 services/policy/db/subject_mappings.go | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/services/policy/db/subject_mappings.go b/services/policy/db/subject_mappings.go
index 8c46300e1c..03f3ffca35 100644
--- a/services/policy/db/subject_mappings.go
+++ b/services/policy/db/subject_mappings.go
@@ -171,7 +171,7 @@ func subjectMappingSelect() sq.SelectBuilder {
 		GroupBy(scsT.Field("id"))
 }
 
-func subjectMappingHydrateItem(row pgx.Row) (*subjectmapping.SubjectMapping, error) {
+func subjectMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*subjectmapping.SubjectMapping, error) {
 	var (
 		id                 string
 		actionsJSON        []byte
@@ -208,9 +208,9 @@ func subjectMappingHydrateItem(row pgx.Row) (*subjectmapping.SubjectMapping, err
 		}
 	}
 
-	av := attributes.Value{}
+	av := &attributes.Value{}
 	if attributeValueJSON != nil {
-		if err := protojson.Unmarshal(attributeValueJSON, &av); err != nil {
+		if av, err = convertJSONToAttrVal(c, attributeValueJSON); err != nil {
 			slog.Error("failed to unmarshal attribute value", slog.String("error", err.Error()), slog.String("attribute value JSON", string(attributeValueJSON)))
 			return nil, err
 		}
@@ -235,16 +235,16 @@ func subjectMappingHydrateItem(row pgx.Row) (*subjectmapping.SubjectMapping, err
 	return &subjectmapping.SubjectMapping{
 		Id:                  id,
 		Metadata:            m,
-		AttributeValue:      &av,
+		AttributeValue:      av,
 		SubjectConditionSet: &scs,
 		Actions:             a,
 	}, nil
 }
 
-func subjectMappingHydrateList(rows pgx.Rows) ([]*subjectmapping.SubjectMapping, error) {
+func subjectMappingHydrateList(c PolicyDbClient, rows pgx.Rows) ([]*subjectmapping.SubjectMapping, error) {
 	list := make([]*subjectmapping.SubjectMapping, 0)
 	for rows.Next() {
-		s, err := subjectMappingHydrateItem(rows)
+		s, err := subjectMappingHydrateItem(c, rows)
 		if err != nil {
 			return nil, err
 		}
@@ -532,7 +532,7 @@ func (c PolicyDbClient) GetSubjectMapping(ctx context.Context, id string) (*subj
 		return nil, err
 	}
 
-	return subjectMappingHydrateItem(row)
+	return subjectMappingHydrateItem(c, row)
 }
 
 func listSubjectMappingsSql() (string, []interface{}, error) {
@@ -554,7 +554,7 @@ func (c PolicyDbClient) ListSubjectMappings(ctx context.Context) ([]*subjectmapp
 	}
 	defer rows.Close()
 
-	subjectMappings, err := subjectMappingHydrateList(rows)
+	subjectMappings, err := subjectMappingHydrateList(c, rows)
 	if err != nil {
 		return nil, err
 	}
@@ -749,5 +749,5 @@ func (c PolicyDbClient) GetMatchedSubjectMappings(ctx context.Context, propertie
 	}
 	defer rows.Close()
 
-	return subjectMappingHydrateList(rows)
+	return subjectMappingHydrateList(c, rows)
 }

From 264d2f12378ad43428a76ff55ed9a968e9d3f15e Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Tue, 12 Mar 2024 16:06:36 -0400
Subject: [PATCH 04/31] clean up

---
 services/policy/db/attribute_values.go | 96 +-------------------------
 services/policy/db/attributes.go       | 11 ---
 2 files changed, 3 insertions(+), 104 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 02806df563..f27eb48182 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -22,7 +22,7 @@ type attributeValueSelectOptions struct {
 
 func getMembersFromStringArray(c PolicyDbClient, members []string) ([]*attributes.Value, error) {
 	// Hydrate members
-	hydratedMemberIds := set.NewSet()
+	hydratedMemberIds := map[string]bool{}
 	var hydratedMembers []*attributes.Value
 
 	for _, member := range members {
@@ -47,12 +47,12 @@ func getMembersFromStringArray(c PolicyDbClient, members []string) ([]*attribute
 			return nil, err
 		}
 
-		if hydratedMemberIds.Contains(member_id) {
+		if hydratedMemberIds[member_id] {
 			slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
 			continue
 		}
 
-		hydratedMemberIds.Add(member_id)
+		hydratedMemberIds[member_id] = true
 		hydratedMembers = append(hydratedMembers, attr)
 	}
 	return hydratedMembers, nil
@@ -82,7 +82,6 @@ func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValu
 	if opts.withFqn {
 		fields = append(fields, &fqn)
 	}
-	println("fqn", fqn.String)
 	if err := row.Scan(fields...); err != nil {
 		fields := []interface{}{
 			&id,
@@ -104,39 +103,9 @@ func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValu
 			return nil, err
 		}
 	} else {
-		// for _, memberJson := range membersJson {
-		// 	// memberJson = memberJson.(json.RawMessage)
-		// 	println("memberJson", string(memberJson))
-		// 	// var i interface{}
-		// 	// if err := json.Unmarshal(memberJson, &i); err != nil {
-		// 	// 	return nil, err
-		// 	// }
-		// 	// memberattributesValuesProtojson(membersJson)
-
-		// 	member, err := attributesValuesProtojson(c, memberJson)
-		// 	if err != nil {
-		// 		return nil, err
-		// 	}
-		// 	// member := &attributes.Value{}
-		// 	// if err := protojson.Unmarshal(memberJson, member); err != nil {
-		// 	// 	return nil, err
-		// 	// }
-		// 	members = append(members, member)
-		// }
-		println("membersJson before", string(membersJson))
 		if membersJson != nil {
 			members, err = attributesValuesProtojson(c, membersJson)
-			println("len(members)", len(members))
-			for _, member := range members {
-				println("member", member.Id)
-			}
-			// if len(members) == 0 {
-			// 	// log.Fatal("members is empty")
-			// 	println("members is empty")
-			// }
-			// log.Fatal("IsSuE In UnMaRsHaLlInG")
 			if err != nil {
-				println("IsSuE In UnMaRsHaLlInG")
 				return nil, err
 			}
 		}
@@ -148,46 +117,6 @@ func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValu
 			return nil, err
 		}
 	}
-	println("fqn: ", fqn.String)
-
-	// // Hydrate members
-	// hydratedMemberIds := set.NewSet()
-	// var hydratedMembers []*attributes.Value
-
-	// for _, member := range members {
-	// 	var (
-	// 		vm_id     string
-	// 		value_id  string
-	// 		member_id string
-	// 	)
-
-	// 	// Get member value from db
-	// 	sql, args, err := getMemberSql(member)
-	// 	if err != nil {
-	// 		return nil, err
-	// 	}
-	// 	if r, err := c.QueryRow(context.TODO(), sql, args, err); err != nil {
-	// 		return nil, err
-	// 	} else if err := r.Scan(&vm_id, &value_id, &member_id); err != nil {
-	// 		return nil, db.WrapIfKnownInvalidQueryErr(err)
-	// 	}
-	// 	attr, err := c.GetAttributeValue(context.TODO(), member_id)
-	// 	if err != nil {
-	// 		return nil, err
-	// 	}
-
-	// 	if hydratedMemberIds.Contains(member_id) {
-	// 		slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
-	// 		continue
-	// 	}
-
-	// 	hydratedMemberIds.Add(member_id)
-	// 	hydratedMembers = append(hydratedMembers, attr)
-	// }
-	// hydratedMembers, err := getMembersFromStringArray(c, memberUUIDs)
-	// if err != nil {
-	// 	return nil, err
-	// }
 
 	v := &attributes.Value{
 		Id:       id,
@@ -255,13 +184,11 @@ func createAttributeValueSql(
 		Columns(
 			"attribute_definition_id",
 			"value",
-			// "members",
 			"metadata",
 		).
 		Values(
 			attribute_id,
 			value,
-			// members,
 			metadata,
 		).
 		Suffix("RETURNING id").
@@ -277,7 +204,6 @@ func (c PolicyDbClient) CreateAttributeValue(ctx context.Context, attributeId st
 	sql, args, err := createAttributeValueSql(
 		attributeId,
 		v.Value,
-		// v.Members,
 		metadataJson,
 	)
 	if err != nil {
@@ -358,12 +284,6 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 	}
 	members += ")) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members"
 	fields := []string{
-		// t.Field("id"),
-		// t.Field("value"),
-		// t.Field("active"),
-		// t.Field("members"),
-		// t.Field("metadata"),
-		// t.Field("attribute_definition_id"),
 		"av.id",
 		"av.value",
 		"av.active",
@@ -372,14 +292,12 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 		"av.attribute_definition_id",
 	}
 	if opts.withFqn {
-		// fields = append(fields, "MAX("+fqnT.Field("fqn")+") AS fqn")
 		fields = append(fields, Tables.AttrFqn.Field("fqn"))
 	}
 
 	sb := db.NewStatementBuilder().
 		Select(fields...).
 		From(t.Name() + " av")
-		// add alias
 
 	// join members
 	sb = sb.LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id")
@@ -389,7 +307,6 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 
 	if opts.withFqn {
 		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + "vmv.id")
-		// sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("attribute_id") + " = " + "vmv.attribute_definition_id")
 	}
 
 	return sb.Where(sq.Eq{
@@ -398,7 +315,6 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 			"av.id",
 			fqnT.Field("fqn"),
 		).
-		// LeftJoin(t.Name() + " ON " + t.Field("id") + " = " + db.Tables.ValueMembers.Field("member_id")).
 		ToSql()
 }
 
@@ -504,7 +420,6 @@ func (c PolicyDbClient) ListAllAttributeValues(ctx context.Context, state string
 
 func updateAttributeValueSql(
 	id string,
-	// members []string,
 	metadata []byte,
 ) (string, []interface{}, error) {
 	t := Tables.AttributeValues
@@ -514,10 +429,6 @@ func updateAttributeValueSql(
 		sb = sb.Set("metadata", metadata)
 	}
 
-	// if members != nil {
-	// 	sb = sb.Set("members", members)
-	// }
-
 	return sb.Where(sq.Eq{t.Field("id"): id}).ToSql()
 }
 
@@ -535,7 +446,6 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 
 	sql, args, err := updateAttributeValueSql(
 		r.Id,
-		// r.Members,
 		metadataJson,
 	)
 	if db.IsQueryBuilderSetClauseError(err) {
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index ff1560eaa4..58ae441d93 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -51,10 +51,6 @@ func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*attributes.Valu
 		item.Metadata = &common.Metadata{}
 	}
 
-	// if item.Active == nil {
-	// 	item.Active = &wrapperspb.BoolValue{Value: true}
-	// }
-
 	var members []*attributes.Value
 	if len(item.Members) > 0 {
 		attr, err := c.GetAttributeValue(context.TODO(), item.Id)
@@ -63,7 +59,6 @@ func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*attributes.Valu
 		}
 		return attr, nil
 	}
-	println("r", string(r))
 	return &attributes.Value{
 		Id:       item.Id,
 		Value:    item.Value,
@@ -93,13 +88,7 @@ func attributesValuesProtojson(c PolicyDbClient, valuesJson []byte) ([]*attribut
 		return values, nil
 	}
 
-	// log.Fatal("valuesJson", string(valuesJson))
-
 	for _, r := range raw {
-		println("r", string(r))
-		// if string(r) == "[]" {
-		// 	continue
-		// }
 		value, err := convertJSONToAttrVal(c, r)
 		if err != nil {
 			return nil, err

From 91198e35661bc1ef76bfd24a836f689e524068c7 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Tue, 12 Mar 2024 16:53:57 -0400
Subject: [PATCH 05/31] change fqn table on condition

---
 services/policy/db/attribute_values.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index f27eb48182..b586d543c9 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -306,7 +306,7 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 	sb = sb.JoinClause("FULL OUTER JOIN " + t.Name() + " vmv ON vm.member_id = vmv.id")
 
 	if opts.withFqn {
-		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + "vmv.id")
+		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + "av.id")
 	}
 
 	return sb.Where(sq.Eq{

From 4da80e47da982753870592bf48dade06f490622c Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Tue, 12 Mar 2024 17:20:19 -0400
Subject: [PATCH 06/31] better fqn support

---
 services/policy/db/attribute_values.go | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index b586d543c9..b36f6ce29d 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -280,7 +280,7 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 		"'metadata', vmv.metadata ," +
 		"'attribute_id', vmv.attribute_definition_id "
 	if opts.withFqn {
-		members += ", 'fqn', " + fqnT.Field("fqn")
+		members += ", 'fqn', " + "fqn1.fqn"
 	}
 	members += ")) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members"
 	fields := []string{
@@ -292,7 +292,7 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 		"av.attribute_definition_id",
 	}
 	if opts.withFqn {
-		fields = append(fields, Tables.AttrFqn.Field("fqn"))
+		fields = append(fields, "MAX(fqn2.fqn) AS fqn")
 	}
 
 	sb := db.NewStatementBuilder().
@@ -306,14 +306,15 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 	sb = sb.JoinClause("FULL OUTER JOIN " + t.Name() + " vmv ON vm.member_id = vmv.id")
 
 	if opts.withFqn {
-		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + "av.id")
+		sb = sb.LeftJoin(fqnT.Name() + " AS fqn1 ON " + "fqn1.value_id" + " = " + "vmv.id")
+		sb = sb.LeftJoin(fqnT.Name() + " AS fqn2 ON " + "fqn2.value_id" + " = " + "av.id")
 	}
 
 	return sb.Where(sq.Eq{
 		"av.id": id}).
 		GroupBy(
 			"av.id",
-			fqnT.Field("fqn"),
+			// fqnT.Field("fqn"),
 		).
 		ToSql()
 }

From 6a35e05ea941eafda75ce1540998a336f129273a Mon Sep 17 00:00:00 2001
From: jakedoublev 
Date: Wed, 13 Mar 2024 09:25:07 -0400
Subject: [PATCH 07/31] rename migration files to reorder

---
 ...create_val_members.md => 20240313000000_create_val_members.md} | 0
 ...eate_val_members.sql => 20240313000000_create_val_members.sql} | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename migrations/{20240223000000_create_val_members.md => 20240313000000_create_val_members.md} (100%)
 rename migrations/{20240223000000_create_val_members.sql => 20240313000000_create_val_members.sql} (100%)

diff --git a/migrations/20240223000000_create_val_members.md b/migrations/20240313000000_create_val_members.md
similarity index 100%
rename from migrations/20240223000000_create_val_members.md
rename to migrations/20240313000000_create_val_members.md
diff --git a/migrations/20240223000000_create_val_members.sql b/migrations/20240313000000_create_val_members.sql
similarity index 100%
rename from migrations/20240223000000_create_val_members.sql
rename to migrations/20240313000000_create_val_members.sql

From 716022f057809f29e750a39138448c630180dbf8 Mon Sep 17 00:00:00 2001
From: jakedoublev 
Date: Wed, 13 Mar 2024 09:54:06 -0400
Subject: [PATCH 08/31] placeholder to bring in subject mappings into the value

---
 services/policy/db/attributes.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index e8b3ff83c2..60243136a6 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -40,6 +40,7 @@ func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*policy.Value, e
 		Members []string `protobuf:"bytes,5,rep,name=members,proto3" json:"members,omitempty"`
 		// list of key access servers
 		Grants []*kasregistry.KeyAccessServer `protobuf:"bytes,6,rep,name=grants,proto3" json:"grants,omitempty"`
+		// SubjectMappings []*policy.SubjectMapping `protobuf:"bytes,7,rep,name=subject_mappings,json=subjectMappings,proto3" json:"subject_mappings,omitempty"`
 		Fqn    string                         `protobuf:"bytes,7,opt,name=fqn,proto3" json:"fqn,omitempty"`
 		Active bool                           `protobuf:"bytes,8,opt,name=active,proto3" json:"active,omitempty"`
 	}

From 968d523f909b4bfd5c98eecaf11f4fcdc2a34624 Mon Sep 17 00:00:00 2001
From: jakedoublev 
Date: Wed, 13 Mar 2024 12:07:44 -0400
Subject: [PATCH 09/31] unmarshaling improvements with successful members
 provision on get value and work identified to populate members when getting
 by attribute that contains values with members

---
 services/policy/db/attribute_values.go | 171 ++++++++++++-------------
 services/policy/db/attributes.go       | 117 +++++++++--------
 services/policy/db/resource_mapping.go |  19 +--
 services/policy/db/subject_mappings.go |  14 +-
 4 files changed, 161 insertions(+), 160 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 38d239ceb1..8cb01ad5e1 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -3,6 +3,7 @@ package db
 import (
 	"context"
 	"database/sql"
+	"fmt"
 	"log/slog"
 
 	sq "github.com/Masterminds/squirrel"
@@ -28,45 +29,45 @@ type attributeValueSelectOptions struct {
 	// withAttributeNamespace       bool
 }
 
-func getMembersFromStringArray(c PolicyDbClient, members []string) ([]*policy.Value, error) {
-	// Hydrate members
-	hydratedMemberIds := map[string]bool{}
-	var hydratedMembers []*policy.Value
-
-	for _, member := range members {
-		var (
-			vm_id     string
-			value_id  string
-			member_id string
-		)
-
-		// Get member value from db
-		sql, args, err := getMemberSql(member)
-		if err != nil {
-			return nil, err
-		}
-		if r, err := c.QueryRow(context.TODO(), sql, args, err); err != nil {
-			return nil, err
-		} else if err := r.Scan(&vm_id, &value_id, &member_id); err != nil {
-			return nil, db.WrapIfKnownInvalidQueryErr(err)
-		}
-		attr, err := c.GetAttributeValue(context.TODO(), member_id)
-		if err != nil {
-			return nil, err
-		}
-
-		if hydratedMemberIds[member_id] {
-			slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
-			continue
-		}
-
-		hydratedMemberIds[member_id] = true
-		hydratedMembers = append(hydratedMembers, attr)
-	}
-	return hydratedMembers, nil
-}
-
-func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValueSelectOptions) (*policy.Value, error) {
+// func getMembersFromStringArray(c PolicyDbClient, members []string) ([]*policy.Value, error) {
+// 	// Hydrate members
+// 	hydratedMemberIds := map[string]bool{}
+// 	var hydratedMembers []*policy.Value
+
+// 	for _, member := range members {
+// 		var (
+// 			vm_id     string
+// 			value_id  string
+// 			member_id string
+// 		)
+
+// 		// Get member value from db
+// 		sql, args, err := getMemberSql(member)
+// 		if err != nil {
+// 			return nil, err
+// 		}
+// 		if r, err := c.QueryRow(context.TODO(), sql, args, err); err != nil {
+// 			return nil, err
+// 		} else if err := r.Scan(&vm_id, &value_id, &member_id); err != nil {
+// 			return nil, db.WrapIfKnownInvalidQueryErr(err)
+// 		}
+// 		attr, err := c.GetAttributeValue(context.TODO(), member_id)
+// 		if err != nil {
+// 			return nil, err
+// 		}
+
+// 		if hydratedMemberIds[member_id] {
+// 			slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
+// 			continue
+// 		}
+
+// 		hydratedMemberIds[member_id] = true
+// 		hydratedMembers = append(hydratedMembers, attr)
+// 	}
+// 	return hydratedMembers, nil
+// }
+
+func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*policy.Value, error) {
 	var (
 		id           string
 		value        string
@@ -75,7 +76,6 @@ func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValu
 		metadataJson []byte
 		attributeId  string
 		fqn          sql.NullString
-		memberUUIDs  []string
 		members      []*policy.Value
 	)
 	fields := []interface{}{
@@ -91,31 +91,17 @@ func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValu
 		fields = append(fields, &fqn)
 	}
 	if err := row.Scan(fields...); err != nil {
-		fields := []interface{}{
-			&id,
-			&value,
-			&active,
-			&memberUUIDs,
-			&metadataJson,
-			&attributeId,
-		}
-		if opts.withFqn {
-			fields = append(fields, &fqn)
-		}
-
-		if err := row.Scan(fields...); err != nil {
-			return nil, db.WrapIfKnownInvalidQueryErr(err)
-		}
-		members, err = getMembersFromStringArray(c, memberUUIDs)
-		if err != nil {
-			return nil, err
-		}
+		fmt.Println("error scanning row: ", err)
 	} else {
+		fmt.Println("no error!")
 		if membersJson != nil {
-			members, err = attributesValuesProtojson(c, membersJson)
+			fmt.Println("membersJson: ", string(membersJson))
+			members, err = attributesValuesProtojson(membersJson)
 			if err != nil {
+				fmt.Println("error unmarshalling members: ", err)
 				return nil, err
 			}
+			fmt.Println("members: ", members)
 		}
 	}
 
@@ -132,15 +118,18 @@ func attributeValueHydrateItem(c PolicyDbClient, row pgx.Row, opts attributeValu
 		Active:   &wrapperspb.BoolValue{Value: active},
 		Members:  members,
 		Metadata: m,
-		Fqn:      fqn.String,
+		Attribute: &policy.Attribute{
+			Id: attributeId,
+		},
+		Fqn: fqn.String,
 	}
 	return v, nil
 }
 
-func attributeValueHydrateItems(c PolicyDbClient, rows pgx.Rows, opts attributeValueSelectOptions) ([]*policy.Value, error) {
+func attributeValueHydrateItems(rows pgx.Rows, opts attributeValueSelectOptions) ([]*policy.Value, error) {
 	list := make([]*policy.Value, 0)
 	for rows.Next() {
-		v, err := attributeValueHydrateItem(c, rows, opts)
+		v, err := attributeValueHydrateItem(rows, opts)
 		if err != nil {
 			return nil, err
 		}
@@ -260,22 +249,22 @@ func (c PolicyDbClient) CreateAttributeValue(ctx context.Context, attributeId st
 	return rV, nil
 }
 
-func getMemberSql(id string) (string, []interface{}, error) {
-	t := Tables.ValueMembers
-	fields := []string{
-		t.Field("id"),
-		t.Field("value_id"),
-		t.Field("member_id"),
-	}
+// func getMemberSql(id string) (string, []interface{}, error) {
+// 	t := Tables.ValueMembers
+// 	fields := []string{
+// 		t.Field("id"),
+// 		t.Field("value_id"),
+// 		t.Field("member_id"),
+// 	}
 
-	sb := db.NewStatementBuilder().
-		Select(fields...).
-		From(t.Name())
+// 	sb := db.NewStatementBuilder().
+// 		Select(fields...).
+// 		From(t.Name())
 
-	return sb.
-		Where(sq.Eq{t.Field("id"): id}).
-		ToSql()
-}
+// 	return sb.
+// 		Where(sq.Eq{t.Field("id"): id}).
+// 		ToSql()
+// }
 
 func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string, []interface{}, error) {
 	t := Tables.AttributeValues
@@ -285,8 +274,9 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 		"'value', vmv.value, " +
 		"'active', vmv.active, " +
 		"'members', vmv.members || ARRAY[]::UUID[], " +
-		"'metadata', vmv.metadata ," +
-		"'attribute_id', vmv.attribute_definition_id "
+		"'metadata', vmv.metadata, " +
+		"'attribute', JSON_BUILD_OBJECT(" +
+		"'id', vmv.attribute_definition_id )" // TODO: get the rest of the attribute here from the JOIN?
 	if opts.withFqn {
 		members += ", 'fqn', " + "fqn1.fqn"
 	}
@@ -331,13 +321,14 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 func (c PolicyDbClient) GetAttributeValue(ctx context.Context, id string) (*policy.Value, error) {
 	opts := attributeValueSelectOptions{withFqn: true}
 	sql, args, err := getAttributeValueSql(id, opts)
+	fmt.Println("\nsql: ", sql)
 	row, err := c.QueryRow(ctx, sql, args, err)
 	if err != nil {
 		slog.Error("error getting attribute value", slog.String("id", id), slog.String("sql", sql), slog.String("error", err.Error()))
 		return nil, err
 	}
 
-	a, err := attributeValueHydrateItem(c, row, opts)
+	a, err := attributeValueHydrateItem(row, opts)
 	if err != nil {
 		slog.Error("error hydrating attribute value", slog.String("id", id), slog.String("sql", sql), slog.String("error", err.Error()))
 		return nil, err
@@ -388,7 +379,7 @@ func (c PolicyDbClient) ListAttributeValues(ctx context.Context, attribute_id st
 		return nil, err
 	}
 	defer rows.Close()
-	return attributeValueHydrateItems(c, rows, opts)
+	return attributeValueHydrateItems(rows, opts)
 }
 
 func listAllAttributeValuesSql(opts attributeValueSelectOptions) (string, []interface{}, error) {
@@ -425,7 +416,7 @@ func (c PolicyDbClient) ListAllAttributeValues(ctx context.Context, state string
 		return nil, err
 	}
 	defer rows.Close()
-	return attributeValueHydrateItems(c, rows, opts)
+	return attributeValueHydrateItems(rows, opts)
 }
 
 func updateAttributeValueSql(
@@ -510,14 +501,14 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 		}
 	}
 
-	var members []*policy.Value
-	for _, member := range r.Members {
-		attr, err := c.GetAttributeValue(ctx, member)
-		if err != nil {
-			return nil, err
-		}
-		members = append(members, attr)
-	}
+	// var members []*policy.Value
+	// for _, member := range r.Members {
+	// 	attr, err := c.GetAttributeValue(ctx, member)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+	// 	members = append(members, attr)
+	// }
 
 	// Update FQN
 	c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueId: r.Id})
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index 60243136a6..a6f06d40c8 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"database/sql"
 	"encoding/json"
+	"fmt"
 	"log/slog"
 	"strings"
 
@@ -29,49 +30,50 @@ func attributesRuleTypeEnumTransformOut(value string) policy.AttributeRuleTypeEn
 	return policy.AttributeRuleTypeEnum(policy.AttributeRuleTypeEnum_value[AttributeRuleTypeEnumPrefix+value])
 }
 
-func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*policy.Value, error) {
-	type AttributeValueDBItem struct {
-		// generated uuid in database
-		Id          string           `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-		Metadata    *common.Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"`
-		AttributeId string           `protobuf:"bytes,3,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"`
-		Value       string           `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
-		// list of attribute values that this value is related to (attribute group)
-		Members []string `protobuf:"bytes,5,rep,name=members,proto3" json:"members,omitempty"`
-		// list of key access servers
-		Grants []*kasregistry.KeyAccessServer `protobuf:"bytes,6,rep,name=grants,proto3" json:"grants,omitempty"`
-		// SubjectMappings []*policy.SubjectMapping `protobuf:"bytes,7,rep,name=subject_mappings,json=subjectMappings,proto3" json:"subject_mappings,omitempty"`
-		Fqn    string                         `protobuf:"bytes,7,opt,name=fqn,proto3" json:"fqn,omitempty"`
-		Active bool                           `protobuf:"bytes,8,opt,name=active,proto3" json:"active,omitempty"`
-	}
-	var item AttributeValueDBItem
-	if err := json.Unmarshal(r, &item); err != nil {
-		return nil, err
-	}
-	if item.Metadata == nil {
-		item.Metadata = &common.Metadata{}
-	}
-
-	var members []*policy.Value
-	if len(item.Members) > 0 {
-		attr, err := c.GetAttributeValue(context.TODO(), item.Id)
-		if err != nil {
-			return nil, err
-		}
-		return attr, nil
-	}
-	return &policy.Value{
-		Id:       item.Id,
-		Value:    item.Value,
-		Members:  members,
-		Metadata: item.Metadata,
-		Fqn:      item.Fqn,
-		Grants:   item.Grants,
-		Active:   &wrapperspb.BoolValue{Value: item.Active},
-	}, nil
-}
-
-func attributesValuesProtojson(c PolicyDbClient, valuesJson []byte) ([]*policy.Value, error) {
+// func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*policy.Value, error) {
+// 	type AttributeValueDBItem struct {
+// 		// generated uuid in database
+// 		Id          string           `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+// 		Metadata    *common.Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"`
+// 		AttributeId string           `protobuf:"bytes,3,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"`
+// 		Value       string           `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
+// 		// list of attribute values that this value is related to (attribute group)
+// 		Members []string `protobuf:"bytes,5,rep,name=members,proto3" json:"members,omitempty"`
+// 		// list of key access servers
+// 		Grants          []*kasregistry.KeyAccessServer `protobuf:"bytes,6,rep,name=grants,proto3" json:"grants,omitempty"`
+// 		SubjectMappings []*policy.SubjectMapping       `protobuf:"bytes,7,rep,name=subject_mappings,json=subjectMappings,proto3" json:"subject_mappings,omitempty"`
+// 		Fqn             string                         `protobuf:"bytes,7,opt,name=fqn,proto3" json:"fqn,omitempty"`
+// 		Active          bool                           `protobuf:"bytes,8,opt,name=active,proto3" json:"active,omitempty"`
+// 	}
+// 	var item AttributeValueDBItem
+// 	if err := json.Unmarshal(r, &item); err != nil {
+// 		return nil, err
+// 	}
+// 	if item.Metadata == nil {
+// 		item.Metadata = &common.Metadata{}
+// 	}
+
+// 	var members []*policy.Value
+// 	if len(item.Members) > 0 {
+// 		attr, err := c.GetAttributeValue(context.TODO(), item.Id)
+// 		if err != nil {
+// 			return nil, err
+// 		}
+// 		return attr, nil
+// 	}
+// 	return &policy.Value{
+// 		Id:              item.Id,
+// 		Value:           item.Value,
+// 		Members:         members,
+// 		SubjectMappings: item.SubjectMappings,
+// 		Metadata:        item.Metadata,
+// 		Fqn:             item.Fqn,
+// 		Grants:          item.Grants,
+// 		Active:          &wrapperspb.BoolValue{Value: item.Active},
+// 	}, nil
+// }
+
+func attributesValuesProtojson(valuesJson []byte) ([]*policy.Value, error) {
 	var (
 		raw    []json.RawMessage
 		values []*policy.Value
@@ -90,12 +92,15 @@ func attributesValuesProtojson(c PolicyDbClient, valuesJson []byte) ([]*policy.V
 	}
 
 	for _, r := range raw {
-		value, err := convertJSONToAttrVal(c, r)
+		value := &policy.Value{}
+		err := protojson.Unmarshal(r, value)
 		if err != nil {
+			fmt.Println("error unmarshaling a value: ", err, string(r))
 			return nil, err
 		}
 		values = append(values, value)
 	}
+	fmt.Println("values: ", values)
 	return values, nil
 }
 
@@ -135,7 +140,7 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 			"JSON_BUILD_OBJECT(" +
 			"'id', " + avt.Field("id") + ", " +
 			"'value', " + avt.Field("value") + "," +
-			"'members', " + avt.Field("members") + "," +
+			"'members', " + avt.Field("members") + "," + // TODO: make sure we keep the same structure here to select all members
 			"'active', " + avt.Field("active")
 
 		// include the subject mapping / subject condition set for each value
@@ -219,7 +224,7 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 	return sb.GroupBy(g...)
 }
 
-func attributesHydrateItem(c PolicyDbClient, row pgx.Row, opts attributesSelectOptions) (*policy.Attribute, error) {
+func attributesHydrateItem(row pgx.Row, opts attributesSelectOptions) (*policy.Attribute, error) {
 	if opts.withKeyAccessGrants {
 		opts.withAttributeValues = true
 	}
@@ -263,7 +268,7 @@ func attributesHydrateItem(c PolicyDbClient, row pgx.Row, opts attributesSelectO
 
 	var v []*policy.Value
 	if valuesJson != nil {
-		v, err = attributesValuesProtojson(c, valuesJson)
+		v, err = attributesValuesProtojson(valuesJson)
 		if err != nil {
 			slog.Error("could not unmarshal values", slog.String("error", err.Error()))
 			return nil, err
@@ -293,10 +298,10 @@ func attributesHydrateItem(c PolicyDbClient, row pgx.Row, opts attributesSelectO
 	return attr, nil
 }
 
-func attributesHydrateList(c PolicyDbClient, rows pgx.Rows, opts attributesSelectOptions) ([]*policy.Attribute, error) {
+func attributesHydrateList(rows pgx.Rows, opts attributesSelectOptions) ([]*policy.Attribute, error) {
 	list := make([]*policy.Attribute, 0)
 	for rows.Next() {
-		attr, err := attributesHydrateItem(c, rows, opts)
+		attr, err := attributesHydrateItem(rows, opts)
 		if err != nil {
 			return nil, err
 		}
@@ -336,7 +341,7 @@ func (c PolicyDbClient) ListAllAttributes(ctx context.Context, state string) ([]
 	}
 	defer rows.Close()
 
-	list, err := attributesHydrateList(c, rows, opts)
+	list, err := attributesHydrateList(rows, opts)
 	if err != nil {
 		slog.Error("could not hydrate list", slog.String("error", err.Error()))
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -360,7 +365,7 @@ func (c PolicyDbClient) ListAllAttributesWithout(ctx context.Context, state stri
 	}
 	defer rows.Close()
 
-	list, err := attributesHydrateList(c, rows, opts)
+	list, err := attributesHydrateList(rows, opts)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
@@ -379,15 +384,17 @@ func getAttributeSql(id string, opts attributesSelectOptions) (string, []interfa
 
 func (c PolicyDbClient) GetAttribute(ctx context.Context, id string) (*policy.Attribute, error) {
 	opts := attributesSelectOptions{
-		withFqn: true,
+		withFqn:             true,
+		withAttributeValues: true,
 	}
 	sql, args, err := getAttributeSql(id, opts)
+	fmt.Println("\nget attribute sql: ", sql)
 	row, err := c.QueryRow(ctx, sql, args, err)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
-	attribute, err := attributesHydrateItem(c, row, opts)
+	attribute, err := attributesHydrateItem(row, opts)
 	if err != nil {
 		slog.Error("could not hydrate item", slog.String("attributeId", id), slog.String("error", err.Error()))
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -420,7 +427,7 @@ func (c PolicyDbClient) GetAttributeByFqn(ctx context.Context, fqn string) (*pol
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
-	attribute, err := attributesHydrateItem(c, row, opts)
+	attribute, err := attributesHydrateItem(row, opts)
 	if err != nil {
 		slog.Error("could not hydrate item", slog.String("fqn", fqn), slog.String("error", err.Error()))
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
@@ -446,7 +453,7 @@ func (c PolicyDbClient) GetAttributesByNamespace(ctx context.Context, namespaceI
 	}
 	defer rows.Close()
 
-	list, err := attributesHydrateList(c, rows, opts)
+	list, err := attributesHydrateList(rows, opts)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
diff --git a/services/policy/db/resource_mapping.go b/services/policy/db/resource_mapping.go
index 4e59470484..4d0927f15e 100644
--- a/services/policy/db/resource_mapping.go
+++ b/services/policy/db/resource_mapping.go
@@ -14,11 +14,11 @@ import (
 	"google.golang.org/protobuf/encoding/protojson"
 )
 
-func resourceMappingHydrateList(c PolicyDbClient, rows pgx.Rows) ([]*policy.ResourceMapping, error) {
+func resourceMappingHydrateList(rows pgx.Rows) ([]*policy.ResourceMapping, error) {
 	var list []*policy.ResourceMapping
 
 	for rows.Next() {
-		rm, err := resourceMappingHydrateItem(c, rows)
+		rm, err := resourceMappingHydrateItem(rows)
 		if err != nil {
 			return nil, err
 		}
@@ -27,7 +27,7 @@ func resourceMappingHydrateList(c PolicyDbClient, rows pgx.Rows) ([]*policy.Reso
 	return list, nil
 }
 
-func resourceMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*policy.ResourceMapping, error) {
+func resourceMappingHydrateItem(row pgx.Row) (*policy.ResourceMapping, error) {
 	var (
 		id                 string
 		metadataJSON       []byte
@@ -54,9 +54,12 @@ func resourceMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*policy.Resource
 		}
 	}
 
-	attributeValue, err = convertJSONToAttrVal(c, attributeValueJSON)
-	if err != nil {
-		return nil, err
+	av := &policy.Value{}
+	if attributeValueJSON != nil {
+		if err := protojson.Unmarshal(attributeValueJSON, av); err != nil {
+			slog.Error("failed to unmarshal attribute value", slog.String("error", err.Error()), slog.String("attribute value JSON", string(attributeValueJSON)))
+			return nil, err
+		}
 	}
 
 	return &policy.ResourceMapping{
@@ -157,7 +160,7 @@ func (c PolicyDbClient) GetResourceMapping(ctx context.Context, id string) (*pol
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
-	rm, err := resourceMappingHydrateItem(c, row)
+	rm, err := resourceMappingHydrateItem(row)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
@@ -183,7 +186,7 @@ func (c PolicyDbClient) ListResourceMappings(ctx context.Context) ([]*policy.Res
 	}
 	defer rows.Close()
 
-	list, err := resourceMappingHydrateList(c, rows)
+	list, err := resourceMappingHydrateList(rows)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
diff --git a/services/policy/db/subject_mappings.go b/services/policy/db/subject_mappings.go
index ff412458dd..d8054956fa 100644
--- a/services/policy/db/subject_mappings.go
+++ b/services/policy/db/subject_mappings.go
@@ -170,7 +170,7 @@ func subjectMappingSelect() sq.SelectBuilder {
 		GroupBy(scsT.Field("id"))
 }
 
-func subjectMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*policy.SubjectMapping, error) {
+func subjectMappingHydrateItem(row pgx.Row) (*policy.SubjectMapping, error) {
 	var (
 		id                 string
 		actionsJSON        []byte
@@ -209,7 +209,7 @@ func subjectMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*policy.SubjectMa
 
 	av := &policy.Value{}
 	if attributeValueJSON != nil {
-		if av, err = convertJSONToAttrVal(c, attributeValueJSON); err != nil {
+		if err := protojson.Unmarshal(attributeValueJSON, av); err != nil {
 			slog.Error("failed to unmarshal attribute value", slog.String("error", err.Error()), slog.String("attribute value JSON", string(attributeValueJSON)))
 			return nil, err
 		}
@@ -240,10 +240,10 @@ func subjectMappingHydrateItem(c PolicyDbClient, row pgx.Row) (*policy.SubjectMa
 	}, nil
 }
 
-func subjectMappingHydrateList(c PolicyDbClient, rows pgx.Rows) ([]*policy.SubjectMapping, error) {
+func subjectMappingHydrateList(rows pgx.Rows) ([]*policy.SubjectMapping, error) {
 	list := make([]*policy.SubjectMapping, 0)
 	for rows.Next() {
-		s, err := subjectMappingHydrateItem(c, rows)
+		s, err := subjectMappingHydrateItem(rows)
 		if err != nil {
 			return nil, err
 		}
@@ -531,7 +531,7 @@ func (c PolicyDbClient) GetSubjectMapping(ctx context.Context, id string) (*poli
 		return nil, err
 	}
 
-	return subjectMappingHydrateItem(c, row)
+	return subjectMappingHydrateItem(row)
 }
 
 func listSubjectMappingsSql() (string, []interface{}, error) {
@@ -553,7 +553,7 @@ func (c PolicyDbClient) ListSubjectMappings(ctx context.Context) ([]*policy.Subj
 	}
 	defer rows.Close()
 
-	subjectMappings, err := subjectMappingHydrateList(c, rows)
+	subjectMappings, err := subjectMappingHydrateList(rows)
 	if err != nil {
 		return nil, err
 	}
@@ -748,5 +748,5 @@ func (c PolicyDbClient) GetMatchedSubjectMappings(ctx context.Context, propertie
 	}
 	defer rows.Close()
 
-	return subjectMappingHydrateList(c, rows)
+	return subjectMappingHydrateList(rows)
 }

From c5c1514b97585d145e9d25ae132135b6a3b09994 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Wed, 13 Mar 2024 20:35:27 -0400
Subject: [PATCH 10/31] join value members for get attribute call

---
 services/policy/db/attribute_values.go |  2 +-
 services/policy/db/attributes.go       | 17 +++++++++++------
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 8cb01ad5e1..892f627e80 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -301,7 +301,7 @@ func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string,
 	sb = sb.LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id")
 
 	// join attribute values
-	sb = sb.JoinClause("FULL OUTER JOIN " + t.Name() + " vmv ON vm.member_id = vmv.id")
+	sb = sb.LeftJoin(t.Name() + " vmv ON vm.member_id = vmv.id")
 
 	if opts.withFqn {
 		sb = sb.LeftJoin(fqnT.Name() + " AS fqn1 ON " + "fqn1.value_id" + " = " + "vmv.id")
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index a6f06d40c8..e6ec94089b 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -138,10 +138,10 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 	if opts.withAttributeValues || opts.withOneValueByFqn != "" {
 		valueSelect := "JSON_AGG(" +
 			"JSON_BUILD_OBJECT(" +
-			"'id', " + avt.Field("id") + ", " +
-			"'value', " + avt.Field("value") + "," +
-			"'members', " + avt.Field("members") + "," + // TODO: make sure we keep the same structure here to select all members
-			"'active', " + avt.Field("active")
+			"'id', avt.id," +
+			"'value', avt.value," +
+			"'members', avt.members," + // TODO: make sure we keep the same structure here to select all members
+			"'active', avt.active"
 
 		// include the subject mapping / subject condition set for each value
 		if opts.withOneValueByFqn != "" {
@@ -179,7 +179,13 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 		LeftJoin(nt.Name() + " ON " + nt.Field("id") + " = " + t.Field("namespace_id"))
 
 	if opts.withAttributeValues {
-		sb = sb.LeftJoin(avt.Name() + " ON " + avt.Field("attribute_definition_id") + " = " + t.Field("id"))
+		sb = sb.LeftJoin("(SELECT av.id, av.value, av.active, COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+			"'id', vmv.id, " +
+			"'value', vmv.value, " +
+			"'active', vmv.active, " +
+			"'members', vmv.members || ARRAY[]::UUID[], " +
+			"'attribute', JSON_BUILD_OBJECT(" +
+			"'id', vmv.attribute_definition_id ))) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members, av.attribute_definition_id FROM " + avt.Name() + " av LEFT JOIN " + Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id LEFT JOIN " + avt.Name() + " vmv ON vm.member_id = vmv.id GROUP BY av.id) avt ON avt.attribute_definition_id = " + t.Field("id"))
 	}
 	if opts.withKeyAccessGrants {
 		sb = sb.LeftJoin(Tables.AttributeKeyAccessGrants.Name() + " ON " + Tables.AttributeKeyAccessGrants.WithoutSchema().Name() + ".attribute_definition_id = " + t.Field("id")).
@@ -214,7 +220,6 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 				"AND " + avt.Field("id") + " = " + fqnt.Field("value_id"),
 			)
 	}
-
 	g := []string{t.Field("id"), nt.Field("name")}
 
 	if opts.withFqn {

From 5e1f51efd86c2b2d440e49c4f7def5bb56c0471e Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 03:09:42 -0400
Subject: [PATCH 11/31] join value members for list subject mappings call

---
 services/policy/db/attributes.go       |  2 +-
 services/policy/db/subject_mappings.go | 38 +++++++++++++++++++++-----
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index e6ec94089b..0feae5061f 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -140,7 +140,7 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 			"JSON_BUILD_OBJECT(" +
 			"'id', avt.id," +
 			"'value', avt.value," +
-			"'members', avt.members," + // TODO: make sure we keep the same structure here to select all members
+			"'members', avt.members," +
 			"'active', avt.active"
 
 		// include the subject mapping / subject condition set for each value
diff --git a/services/policy/db/subject_mappings.go b/services/policy/db/subject_mappings.go
index d8054956fa..b8d7ea3344 100644
--- a/services/policy/db/subject_mappings.go
+++ b/services/policy/db/subject_mappings.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
+	"log"
 	"log/slog"
 
 	sq "github.com/Masterminds/squirrel"
@@ -146,7 +147,12 @@ func subjectMappingSelect() sq.SelectBuilder {
 	t := Tables.SubjectMappings
 	avT := Tables.AttributeValues
 	scsT := Tables.SubjectConditionSet
-
+	members := "COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+		"'id', vmv.id, " +
+		"'value', vmv.value, " +
+		"'active', vmv.active, " +
+		"'members', vmv.members || ARRAY[]::UUID[] " +
+		")) FILTER (WHERE vmv.id IS NOT NULL ), '[]')"
 	return db.NewStatementBuilder().Select(
 		t.Field("id"),
 		t.Field("actions"),
@@ -157,15 +163,29 @@ func subjectMappingSelect() sq.SelectBuilder {
 			"'subject_sets', "+scsT.Field("condition")+
 			") AS subject_condition_set",
 		"JSON_BUILD_OBJECT("+
-			"'id', "+avT.Field("id")+", "+
-			"'value', "+avT.Field("value")+", "+
-			"'members', "+avT.Field("members")+", "+
-			"'active'", avT.Field("active")+
+			"'id', av.id,"+
+			"'value', av.value,"+
+			"'members', "+members+","+
+			"'active', av.active"+
 			") AS attribute_value",
 	).
-		LeftJoin(avT.Name() + " ON " + t.Field("attribute_value_id") + " = " + avT.Field("id")).
+		// LeftJoin(avT.Name() + " ON " + t.Field("attribute_value_id") + " = " + avT.Field("id")).
+		// GroupBy(t.Field("id")).
+		// GroupBy(avT.Field("id")).
+		// LeftJoin("(SELECT av.id, av.value, av.active, COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+		// 	"'id', vmv.id, " +
+		// 	"'value', vmv.value, " +
+		// 	"'active', vmv.active, " +
+		// 	"'members', vmv.members || ARRAY[]::UUID[], " +
+		// 	"'attribute', JSON_BUILD_OBJECT(" +
+		// 	"'id', vmv.attribute_definition_id ))) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members, av.attribute_definition_id FROM " + avT.Name() + " av LEFT JOIN " + Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id LEFT JOIN " + avT.Name() + " vmv ON vm.member_id = vmv.id GROUP BY av.id) avt ON avt.id = " + t.Field("attribute_value_id")).
+		// GroupBy("avt.id").
+		// GroupBy(t.Field("id")).
+		LeftJoin(avT.Name() + " av ON " + t.Field("attribute_value_id") + " = " + "av.id").
+		LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id").
+		LeftJoin(avT.Name() + " vmv ON vm.member_id = vmv.id").
+		GroupBy("av.id").
 		GroupBy(t.Field("id")).
-		GroupBy(avT.Field("id")).
 		LeftJoin(scsT.Name() + " ON " + scsT.Field("id") + " = " + t.Field("subject_condition_set_id")).
 		GroupBy(scsT.Field("id"))
 }
@@ -196,6 +216,7 @@ func subjectMappingHydrateItem(row pgx.Row) (*policy.SubjectMapping, error) {
 		slog.String("attributeValueJSON", string(attributeValueJSON)),
 	)
 	if err != nil {
+		log.Fatal("HERE")
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 
@@ -536,6 +557,9 @@ func (c PolicyDbClient) GetSubjectMapping(ctx context.Context, id string) (*poli
 
 func listSubjectMappingsSql() (string, []interface{}, error) {
 	t := Tables.SubjectMappings
+	// log.Fatal(subjectMappingSelect().
+	// 	From(t.Name()).
+	// 	ToSql())
 	return subjectMappingSelect().
 		From(t.Name()).
 		ToSql()

From 477f928161b47bcc3ddc79fc19867655cc3a6219 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 03:10:26 -0400
Subject: [PATCH 12/31] clean up

---
 services/policy/db/subject_mappings.go | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/services/policy/db/subject_mappings.go b/services/policy/db/subject_mappings.go
index b8d7ea3344..c20490e82b 100644
--- a/services/policy/db/subject_mappings.go
+++ b/services/policy/db/subject_mappings.go
@@ -169,18 +169,6 @@ func subjectMappingSelect() sq.SelectBuilder {
 			"'active', av.active"+
 			") AS attribute_value",
 	).
-		// LeftJoin(avT.Name() + " ON " + t.Field("attribute_value_id") + " = " + avT.Field("id")).
-		// GroupBy(t.Field("id")).
-		// GroupBy(avT.Field("id")).
-		// LeftJoin("(SELECT av.id, av.value, av.active, COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
-		// 	"'id', vmv.id, " +
-		// 	"'value', vmv.value, " +
-		// 	"'active', vmv.active, " +
-		// 	"'members', vmv.members || ARRAY[]::UUID[], " +
-		// 	"'attribute', JSON_BUILD_OBJECT(" +
-		// 	"'id', vmv.attribute_definition_id ))) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members, av.attribute_definition_id FROM " + avT.Name() + " av LEFT JOIN " + Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id LEFT JOIN " + avT.Name() + " vmv ON vm.member_id = vmv.id GROUP BY av.id) avt ON avt.id = " + t.Field("attribute_value_id")).
-		// GroupBy("avt.id").
-		// GroupBy(t.Field("id")).
 		LeftJoin(avT.Name() + " av ON " + t.Field("attribute_value_id") + " = " + "av.id").
 		LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id").
 		LeftJoin(avT.Name() + " vmv ON vm.member_id = vmv.id").
@@ -557,9 +545,6 @@ func (c PolicyDbClient) GetSubjectMapping(ctx context.Context, id string) (*poli
 
 func listSubjectMappingsSql() (string, []interface{}, error) {
 	t := Tables.SubjectMappings
-	// log.Fatal(subjectMappingSelect().
-	// 	From(t.Name()).
-	// 	ToSql())
 	return subjectMappingSelect().
 		From(t.Name()).
 		ToSql()

From a7fffe7b3f4f059f1017f18a6d9f10114a826a28 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 04:05:01 -0400
Subject: [PATCH 13/31] join value members for get resource mapping call

---
 services/policy/db/resource_mapping.go | 30 ++++++++++++++++++--------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/services/policy/db/resource_mapping.go b/services/policy/db/resource_mapping.go
index 4d0927f15e..bd36f080e5 100644
--- a/services/policy/db/resource_mapping.go
+++ b/services/policy/db/resource_mapping.go
@@ -54,9 +54,10 @@ func resourceMappingHydrateItem(row pgx.Row) (*policy.ResourceMapping, error) {
 		}
 	}
 
-	av := &policy.Value{}
+	// av := &policy.Value{}
 	if attributeValueJSON != nil {
-		if err := protojson.Unmarshal(attributeValueJSON, av); err != nil {
+		println("attributeValueJSON", string(attributeValueJSON))
+		if err := protojson.Unmarshal(attributeValueJSON, attributeValue); err != nil {
 			slog.Error("failed to unmarshal attribute value", slog.String("error", err.Error()), slog.String("attribute value JSON", string(attributeValueJSON)))
 			return nil, err
 		}
@@ -73,19 +74,30 @@ func resourceMappingHydrateItem(row pgx.Row) (*policy.ResourceMapping, error) {
 func resourceMappingSelect() sq.SelectBuilder {
 	t := Tables.ResourceMappings
 	at := Tables.AttributeValues
+	members := "COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+		"'id', vmv.id, " +
+		"'value', vmv.value, " +
+		"'active', vmv.active, " +
+		"'members', vmv.members || ARRAY[]::UUID[] " +
+		")) FILTER (WHERE vmv.id IS NOT NULL ), '[]')"
 	return db.NewStatementBuilder().Select(
 		t.Field("id"),
 		t.Field("metadata"),
 		t.Field("terms"),
 		"JSON_BUILD_OBJECT("+
-			"'id', "+at.Field("id")+", "+
-			"'value', "+at.Field("value")+","+
-			"'members', "+at.Field("members")+
-			")"+
-			" AS attribute_value",
+			"'id', av.id,"+
+			"'value', av.value,"+
+			"'members', "+members+
+			") AS attribute_value",
 	).
-		LeftJoin(at.Name()+" ON "+at.Field("id")+" = "+t.Field("attribute_value_id")).
-		GroupBy(t.Field("id"), at.Field("id"))
+		LeftJoin(at.Name() + " av ON " + t.Field("attribute_value_id") + " = " + "av.id").
+		LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id").
+		LeftJoin(at.Name() + " vmv ON vm.member_id = vmv.id").
+		GroupBy("av.id").
+		GroupBy(t.Field("id"))
+	// GroupBy(t.Field("id"), "av.id")
+	// LeftJoin(at.Name()+" ON "+at.Field("id")+" = "+t.Field("attribute_value_id")).
+	// GroupBy(t.Field("id"), at.Field("id"))
 }
 
 /*

From 5ceeb0e8acd803ae877ecc41fd771112fa5664c5 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 04:05:28 -0400
Subject: [PATCH 14/31] clean up

---
 services/policy/db/resource_mapping.go | 2 --
 1 file changed, 2 deletions(-)

diff --git a/services/policy/db/resource_mapping.go b/services/policy/db/resource_mapping.go
index bd36f080e5..b4782fdb93 100644
--- a/services/policy/db/resource_mapping.go
+++ b/services/policy/db/resource_mapping.go
@@ -54,9 +54,7 @@ func resourceMappingHydrateItem(row pgx.Row) (*policy.ResourceMapping, error) {
 		}
 	}
 
-	// av := &policy.Value{}
 	if attributeValueJSON != nil {
-		println("attributeValueJSON", string(attributeValueJSON))
 		if err := protojson.Unmarshal(attributeValueJSON, attributeValue); err != nil {
 			slog.Error("failed to unmarshal attribute value", slog.String("error", err.Error()), slog.String("attribute value JSON", string(attributeValueJSON)))
 			return nil, err

From e0cd4d96551a596c196779de117866322c34c9a3 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 05:37:14 -0400
Subject: [PATCH 15/31] join value members for list all attr vals call

---
 services/policy/db/attribute_values.go | 89 ++++++++++++++++++++------
 services/policy/db/attributes.go       |  7 +-
 2 files changed, 73 insertions(+), 23 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 892f627e80..db7d10089f 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -91,7 +91,11 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 		fields = append(fields, &fqn)
 	}
 	if err := row.Scan(fields...); err != nil {
-		fmt.Println("error scanning row: ", err)
+		// fmt.Println("error scanning row: ", err)
+		println("GOT HERE")
+		// return nil, err
+		return nil, db.WrapIfKnownInvalidQueryErr(err)
+		// members = make([]*policy.Value, 0)
 	} else {
 		fmt.Println("no error!")
 		if membersJson != nil {
@@ -111,7 +115,10 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 			return nil, err
 		}
 	}
-
+	// if id != "" {
+	// 	return nil, nil
+	// }
+	println("GOT HERE2")
 	v := &policy.Value{
 		Id:       id,
 		Value:    value,
@@ -338,26 +345,47 @@ func (c PolicyDbClient) GetAttributeValue(ctx context.Context, id string) (*poli
 
 func listAttributeValuesSql(attribute_id string, opts attributeValueSelectOptions) (string, []interface{}, error) {
 	t := Tables.AttributeValues
+	members := "COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+		"'id', vmv.id, " +
+		"'value', vmv.value, " +
+		"'active', vmv.active, " +
+		"'members', vmv.members || ARRAY[]::UUID[], " +
+		"'metadata', vmv.metadata, " +
+		"'attribute', JSON_BUILD_OBJECT(" +
+		"'id', vmv.attribute_definition_id )"
+	if opts.withFqn {
+		members += ", 'fqn', " + "fqn1.fqn"
+	}
+	members += ")) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members"
 	fields := []string{
-		t.Field("id"),
-		t.Field("value"),
-		t.Field("active"),
-		t.Field("members"),
-		t.Field("metadata"),
-		t.Field("attribute_definition_id"),
+		"av.id",
+		"av.value",
+		"av.active",
+		members,
+		"av.metadata",
+		"av.attribute_definition_id",
 	}
 	if opts.withFqn {
-		fields = append(fields, "fqn")
+		fields = append(fields, "MAX(fqn2.fqn) AS fqn")
 	}
 
 	sb := db.NewStatementBuilder().
 		Select(fields...)
 
+	// join members
+	sb = sb.LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id")
+
+	// join attribute values
+	sb = sb.LeftJoin(t.Name() + " vmv ON vm.member_id = vmv.id")
+
 	if opts.withFqn {
 		fqnT := Tables.AttrFqn
-		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + t.Field("id"))
+		sb = sb.LeftJoin(fqnT.Name() + " AS fqn1 ON " + "fqn1.value_id" + " = " + "vmv.id")
+		sb = sb.LeftJoin(fqnT.Name() + " AS fqn2 ON " + "fqn2.value_id" + " = " + "av.id")
 	}
 
+	sb = sb.GroupBy("av.id")
+
 	where := sq.Eq{}
 	if opts.state != "" && opts.state != StateAny {
 		where[t.Field("active")] = opts.state == StateActive
@@ -365,7 +393,7 @@ func listAttributeValuesSql(attribute_id string, opts attributeValueSelectOption
 	where[t.Field("attribute_definition_id")] = attribute_id
 
 	return sb.
-		From(t.Name()).
+		From(t.Name() + " av").
 		Where(where).
 		ToSql()
 }
@@ -384,27 +412,48 @@ func (c PolicyDbClient) ListAttributeValues(ctx context.Context, attribute_id st
 
 func listAllAttributeValuesSql(opts attributeValueSelectOptions) (string, []interface{}, error) {
 	t := Tables.AttributeValues
+	members := "COALESCE(JSON_AGG(JSON_BUILD_OBJECT(" +
+		"'id', vmv.id, " +
+		"'value', vmv.value, " +
+		"'active', vmv.active, " +
+		"'members', vmv.members || ARRAY[]::UUID[], " +
+		"'metadata', vmv.metadata, " +
+		"'attribute', JSON_BUILD_OBJECT(" +
+		"'id', vmv.attribute_definition_id )"
+	if opts.withFqn {
+		members += ", 'fqn', " + "fqn1.fqn"
+	}
+	members += ")) FILTER (WHERE vmv.id IS NOT NULL ), '[]') AS members"
 	fields := []string{
-		t.Field("id"),
-		t.Field("value"),
-		t.Field("active"),
-		t.Field("members"),
-		t.Field("metadata"),
-		t.Field("attribute_definition_id"),
+		"av.id",
+		"av.value",
+		"av.active",
+		members,
+		"av.metadata",
+		"av.attribute_definition_id",
 	}
 	if opts.withFqn {
-		fields = append(fields, "fqn")
+		fields = append(fields, "MAX(fqn2.fqn) AS fqn")
 	}
 	sb := db.NewStatementBuilder().
 		Select(fields...)
 
+	// join members
+	sb = sb.LeftJoin(Tables.ValueMembers.Name() + " vm ON av.id = vm.value_id")
+
+	// join attribute values
+	sb = sb.LeftJoin(t.Name() + " vmv ON vm.member_id = vmv.id")
+
 	if opts.withFqn {
 		fqnT := Tables.AttrFqn
-		sb = sb.LeftJoin(fqnT.Name() + " ON " + fqnT.Field("value_id") + " = " + t.Field("id"))
+		sb = sb.LeftJoin(fqnT.Name() + " AS fqn1 ON " + "fqn1.value_id" + " = " + "vmv.id")
+		sb = sb.LeftJoin(fqnT.Name() + " AS fqn2 ON " + "fqn2.value_id" + " = " + "av.id")
 	}
 
+	sb = sb.GroupBy("av.id")
+
 	return sb.
-		From(t.Name()).
+		From(t.Name() + " av").
 		ToSql()
 }
 
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index 0feae5061f..dd404cab94 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -216,8 +216,8 @@ func attributesSelect(opts attributesSelectOptions) sq.SelectBuilder {
 				"INNER JOIN " + fqnt.Name() + " AS inner_fqns ON " + avt.Field("id") + " = inner_fqns.value_id " +
 				"WHERE inner_fqns.fqn = '" + opts.withOneValueByFqn + "' " +
 				"GROUP BY " + avt.Field("id") + ", inner_fqns.fqn " +
-				") AS val_sm_fqn_join ON " + avt.Field("id") + " = val_sm_fqn_join.av_id " +
-				"AND " + avt.Field("id") + " = " + fqnt.Field("value_id"),
+				") AS val_sm_fqn_join ON " + "avt.id" + " = val_sm_fqn_join.av_id " +
+				"AND " + "avt.id" + " = " + fqnt.Field("value_id"),
 			)
 	}
 	g := []string{t.Field("id"), nt.Field("name")}
@@ -270,7 +270,7 @@ func attributesHydrateItem(row pgx.Row, opts attributesSelectOptions) (*policy.A
 			return nil, err
 		}
 	}
-
+	// println("valuesJson: ", string(valuesJson))
 	var v []*policy.Value
 	if valuesJson != nil {
 		v, err = attributesValuesProtojson(valuesJson)
@@ -427,6 +427,7 @@ func (c PolicyDbClient) GetAttributeByFqn(ctx context.Context, fqn string) (*pol
 		opts.withFqn = true
 	}
 	sql, args, err := getAttributeByFqnSql(fqn, opts)
+	// println("sql", sql)
 	row, err := c.QueryRow(ctx, sql, args, err)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)

From 65316a0864a8600a380ea7ae0536d953e01e3f5d Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 05:38:34 -0400
Subject: [PATCH 16/31] clean up

---
 services/policy/db/attribute_values.go | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index db7d10089f..a648f33c06 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -91,21 +91,14 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 		fields = append(fields, &fqn)
 	}
 	if err := row.Scan(fields...); err != nil {
-		// fmt.Println("error scanning row: ", err)
-		println("GOT HERE")
-		// return nil, err
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
-		// members = make([]*policy.Value, 0)
 	} else {
 		fmt.Println("no error!")
 		if membersJson != nil {
-			fmt.Println("membersJson: ", string(membersJson))
 			members, err = attributesValuesProtojson(membersJson)
 			if err != nil {
-				fmt.Println("error unmarshalling members: ", err)
 				return nil, err
 			}
-			fmt.Println("members: ", members)
 		}
 	}
 
@@ -115,10 +108,7 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 			return nil, err
 		}
 	}
-	// if id != "" {
-	// 	return nil, nil
-	// }
-	println("GOT HERE2")
+
 	v := &policy.Value{
 		Id:       id,
 		Value:    value,

From 95112d7356253e3b9564c8eb69506dd536b8e669 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 05:40:53 -0400
Subject: [PATCH 17/31] join value members for list attr vals call

---
 services/policy/db/attribute_values.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index a648f33c06..1bdef38df6 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -378,9 +378,9 @@ func listAttributeValuesSql(attribute_id string, opts attributeValueSelectOption
 
 	where := sq.Eq{}
 	if opts.state != "" && opts.state != StateAny {
-		where[t.Field("active")] = opts.state == StateActive
+		where["av.active"] = opts.state == StateActive
 	}
-	where[t.Field("attribute_definition_id")] = attribute_id
+	where["av.attribute_definition_id"] = attribute_id
 
 	return sb.
 		From(t.Name() + " av").

From e618d92153cec0af9c241a9de368ef6965e27c2a Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 05:51:38 -0400
Subject: [PATCH 18/31] fix deep equality test

---
 integration/attribute_values_test.go | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/integration/attribute_values_test.go b/integration/attribute_values_test.go
index c64019d0fc..1ec6cc47e0 100644
--- a/integration/attribute_values_test.go
+++ b/integration/attribute_values_test.go
@@ -165,7 +165,14 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithMembers_Succeeds()
 	assert.Equal(s.T(), createdValue.Id, got.Id)
 	assert.Equal(s.T(), createdValue.Value, got.Value)
 	assert.EqualValues(s.T(), createdValue.Metadata.Labels, got.Metadata.Labels)
-	assert.EqualValues(s.T(), createdValue.Members, got.Members)
+	assert.Equal(s.T(), len(createdValue.Members), len(got.Members))
+	assert.True(s.T(), len(got.Members) > 0)
+	for idx, member := range got.Members {
+		assert.Equal(s.T(), member.Id, createdValue.Members[idx].Id)
+		assert.Equal(s.T(), member.Value, createdValue.Members[idx].Value)
+		assert.Equal(s.T(), member.Fqn, createdValue.Members[idx].Fqn)
+		assert.Equal(s.T(), member.Active.Value, createdValue.Members[idx].Active.Value)
+	}
 }
 
 func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidAttributeId_Fails() {

From ece2fed17c0ce7cd27dea6bc89f2de9ca6b3b837 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 05:59:31 -0400
Subject: [PATCH 19/31] clean up

---
 services/policy/db/attribute_values.go |  1 -
 services/policy/db/attributes.go       | 46 --------------------------
 services/policy/db/resource_mapping.go |  3 --
 services/policy/db/subject_mappings.go |  2 --
 4 files changed, 52 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 1bdef38df6..ca2ca20e30 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -93,7 +93,6 @@ func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*
 	if err := row.Scan(fields...); err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	} else {
-		fmt.Println("no error!")
 		if membersJson != nil {
 			members, err = attributesValuesProtojson(membersJson)
 			if err != nil {
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index dd404cab94..08615fe8cb 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -30,49 +30,6 @@ func attributesRuleTypeEnumTransformOut(value string) policy.AttributeRuleTypeEn
 	return policy.AttributeRuleTypeEnum(policy.AttributeRuleTypeEnum_value[AttributeRuleTypeEnumPrefix+value])
 }
 
-// func convertJSONToAttrVal(c PolicyDbClient, r json.RawMessage) (*policy.Value, error) {
-// 	type AttributeValueDBItem struct {
-// 		// generated uuid in database
-// 		Id          string           `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-// 		Metadata    *common.Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"`
-// 		AttributeId string           `protobuf:"bytes,3,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"`
-// 		Value       string           `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
-// 		// list of attribute values that this value is related to (attribute group)
-// 		Members []string `protobuf:"bytes,5,rep,name=members,proto3" json:"members,omitempty"`
-// 		// list of key access servers
-// 		Grants          []*kasregistry.KeyAccessServer `protobuf:"bytes,6,rep,name=grants,proto3" json:"grants,omitempty"`
-// 		SubjectMappings []*policy.SubjectMapping       `protobuf:"bytes,7,rep,name=subject_mappings,json=subjectMappings,proto3" json:"subject_mappings,omitempty"`
-// 		Fqn             string                         `protobuf:"bytes,7,opt,name=fqn,proto3" json:"fqn,omitempty"`
-// 		Active          bool                           `protobuf:"bytes,8,opt,name=active,proto3" json:"active,omitempty"`
-// 	}
-// 	var item AttributeValueDBItem
-// 	if err := json.Unmarshal(r, &item); err != nil {
-// 		return nil, err
-// 	}
-// 	if item.Metadata == nil {
-// 		item.Metadata = &common.Metadata{}
-// 	}
-
-// 	var members []*policy.Value
-// 	if len(item.Members) > 0 {
-// 		attr, err := c.GetAttributeValue(context.TODO(), item.Id)
-// 		if err != nil {
-// 			return nil, err
-// 		}
-// 		return attr, nil
-// 	}
-// 	return &policy.Value{
-// 		Id:              item.Id,
-// 		Value:           item.Value,
-// 		Members:         members,
-// 		SubjectMappings: item.SubjectMappings,
-// 		Metadata:        item.Metadata,
-// 		Fqn:             item.Fqn,
-// 		Grants:          item.Grants,
-// 		Active:          &wrapperspb.BoolValue{Value: item.Active},
-// 	}, nil
-// }
-
 func attributesValuesProtojson(valuesJson []byte) ([]*policy.Value, error) {
 	var (
 		raw    []json.RawMessage
@@ -100,7 +57,6 @@ func attributesValuesProtojson(valuesJson []byte) ([]*policy.Value, error) {
 		}
 		values = append(values, value)
 	}
-	fmt.Println("values: ", values)
 	return values, nil
 }
 
@@ -270,7 +226,6 @@ func attributesHydrateItem(row pgx.Row, opts attributesSelectOptions) (*policy.A
 			return nil, err
 		}
 	}
-	// println("valuesJson: ", string(valuesJson))
 	var v []*policy.Value
 	if valuesJson != nil {
 		v, err = attributesValuesProtojson(valuesJson)
@@ -427,7 +382,6 @@ func (c PolicyDbClient) GetAttributeByFqn(ctx context.Context, fqn string) (*pol
 		opts.withFqn = true
 	}
 	sql, args, err := getAttributeByFqnSql(fqn, opts)
-	// println("sql", sql)
 	row, err := c.QueryRow(ctx, sql, args, err)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
diff --git a/services/policy/db/resource_mapping.go b/services/policy/db/resource_mapping.go
index b4782fdb93..2bfe853e9d 100644
--- a/services/policy/db/resource_mapping.go
+++ b/services/policy/db/resource_mapping.go
@@ -93,9 +93,6 @@ func resourceMappingSelect() sq.SelectBuilder {
 		LeftJoin(at.Name() + " vmv ON vm.member_id = vmv.id").
 		GroupBy("av.id").
 		GroupBy(t.Field("id"))
-	// GroupBy(t.Field("id"), "av.id")
-	// LeftJoin(at.Name()+" ON "+at.Field("id")+" = "+t.Field("attribute_value_id")).
-	// GroupBy(t.Field("id"), at.Field("id"))
 }
 
 /*
diff --git a/services/policy/db/subject_mappings.go b/services/policy/db/subject_mappings.go
index c20490e82b..3270df4724 100644
--- a/services/policy/db/subject_mappings.go
+++ b/services/policy/db/subject_mappings.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
-	"log"
 	"log/slog"
 
 	sq "github.com/Masterminds/squirrel"
@@ -204,7 +203,6 @@ func subjectMappingHydrateItem(row pgx.Row) (*policy.SubjectMapping, error) {
 		slog.String("attributeValueJSON", string(attributeValueJSON)),
 	)
 	if err != nil {
-		log.Fatal("HERE")
 		return nil, db.WrapIfKnownInvalidQueryErr(err)
 	}
 

From 53b555077ed54fb8699c8a1bfaf5c870f5fc587a Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 06:01:11 -0400
Subject: [PATCH 20/31] again

---
 services/policy/db/attribute_values.go | 38 --------------------------
 services/policy/db/attributes.go       |  8 ------
 2 files changed, 46 deletions(-)

diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index ca2ca20e30..2bf8bed84e 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -29,44 +29,6 @@ type attributeValueSelectOptions struct {
 	// withAttributeNamespace       bool
 }
 
-// func getMembersFromStringArray(c PolicyDbClient, members []string) ([]*policy.Value, error) {
-// 	// Hydrate members
-// 	hydratedMemberIds := map[string]bool{}
-// 	var hydratedMembers []*policy.Value
-
-// 	for _, member := range members {
-// 		var (
-// 			vm_id     string
-// 			value_id  string
-// 			member_id string
-// 		)
-
-// 		// Get member value from db
-// 		sql, args, err := getMemberSql(member)
-// 		if err != nil {
-// 			return nil, err
-// 		}
-// 		if r, err := c.QueryRow(context.TODO(), sql, args, err); err != nil {
-// 			return nil, err
-// 		} else if err := r.Scan(&vm_id, &value_id, &member_id); err != nil {
-// 			return nil, db.WrapIfKnownInvalidQueryErr(err)
-// 		}
-// 		attr, err := c.GetAttributeValue(context.TODO(), member_id)
-// 		if err != nil {
-// 			return nil, err
-// 		}
-
-// 		if hydratedMemberIds[member_id] {
-// 			slog.Info("attr val member may be duplicated", slog.String("member_id", member_id))
-// 			continue
-// 		}
-
-// 		hydratedMemberIds[member_id] = true
-// 		hydratedMembers = append(hydratedMembers, attr)
-// 	}
-// 	return hydratedMembers, nil
-// }
-
 func attributeValueHydrateItem(row pgx.Row, opts attributeValueSelectOptions) (*policy.Value, error) {
 	var (
 		id           string
diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index 08615fe8cb..b6c8366185 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -36,18 +36,10 @@ func attributesValuesProtojson(valuesJson []byte) ([]*policy.Value, error) {
 		values []*policy.Value
 	)
 
-	if valuesJson == nil {
-		return values, nil
-	}
-
 	if err := json.Unmarshal(valuesJson, &raw); err != nil {
 		return nil, err
 	}
 
-	if len(raw) == 0 {
-		return values, nil
-	}
-
 	for _, r := range raw {
 		value := &policy.Value{}
 		err := protojson.Unmarshal(r, value)

From 3ad315e07ac01cb9b9fbbd1966971a7dc8a1cfc1 Mon Sep 17 00:00:00 2001
From: Krish Suchak <42231639+suchak1@users.noreply.github.com>
Date: Thu, 14 Mar 2024 11:16:10 -0400
Subject: [PATCH 21/31] Update migrations/20240313000000_create_val_members.md

Co-authored-by: Jake Van Vorhis <83739412+jakedoublev@users.noreply.github.com>
---
 migrations/20240313000000_create_val_members.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/migrations/20240313000000_create_val_members.md b/migrations/20240313000000_create_val_members.md
index e7efa6c59c..5075c8796a 100644
--- a/migrations/20240313000000_create_val_members.md
+++ b/migrations/20240313000000_create_val_members.md
@@ -24,6 +24,7 @@ erDiagram
         uuid        id                      PK
         uuid        value_id                FK
         uuid        member_id               FK
+          compIdx comp_key UK "value_id + member_id"
     }
 
 ```

From 08ffa28cfd78c1b240492f3f92af15c4cc7eb37d Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 11:01:33 -0400
Subject: [PATCH 22/31] remove debug statement

---
 services/policy/db/attributes.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/services/policy/db/attributes.go b/services/policy/db/attributes.go
index b6c8366185..620b81da16 100644
--- a/services/policy/db/attributes.go
+++ b/services/policy/db/attributes.go
@@ -340,7 +340,6 @@ func (c PolicyDbClient) GetAttribute(ctx context.Context, id string) (*policy.At
 		withAttributeValues: true,
 	}
 	sql, args, err := getAttributeSql(id, opts)
-	fmt.Println("\nget attribute sql: ", sql)
 	row, err := c.QueryRow(ctx, sql, args, err)
 	if err != nil {
 		return nil, db.WrapIfKnownInvalidQueryErr(err)

From bb2a8fafd7cafd3d7b87adc8ca8ef6536b83696b Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 11:04:37 -0400
Subject: [PATCH 23/31] rename table

---
 internal/fixtures/fixtures.go                 |  4 ++--
 internal/fixtures/policy_fixtures.yaml        |  4 ++--
 .../20240313000000_create_val_members.sql     | 24 +++++++++----------
 services/policy/db/policy.go                  |  2 +-
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/internal/fixtures/fixtures.go b/internal/fixtures/fixtures.go
index e1ebcfdcf6..cc72a6c007 100644
--- a/internal/fixtures/fixtures.go
+++ b/internal/fixtures/fixtures.go
@@ -132,7 +132,7 @@ type FixtureData struct {
 	ValueMembers struct {
 		Metadata FixtureMetadata                   `yaml:"metadata"`
 		Data     map[string]FixtureDataValueMember `yaml:"data"`
-	} `yaml:"value_members"`
+	} `yaml:"attribute_value_members"`
 }
 
 func LoadFixtureData(file string) {
@@ -262,7 +262,7 @@ func (f *Fixtures) Provision() {
 		slog.Int64("namespaces", n),
 		slog.Int64("attributes", a),
 		slog.Int64("attribute_values", aV),
-		slog.Int64("value_members", vM),
+		slog.Int64("attribute_value_members", vM),
 		slog.Int64("subject_mappings", sM),
 		slog.Int64("subject_condition_set", sc),
 		slog.Int64("resource_mappings", rM),
diff --git a/internal/fixtures/policy_fixtures.yaml b/internal/fixtures/policy_fixtures.yaml
index 0ea8d2e455..f0c336d406 100644
--- a/internal/fixtures/policy_fixtures.yaml
+++ b/internal/fixtures/policy_fixtures.yaml
@@ -187,9 +187,9 @@ attribute_value_key_access_servers:
   - value_id: 74babca6-016f-4f3e-a99b-4e46ea8d0fd8
     key_access_server_id: e36640a6-61c5-4d4c-a45b-0e0a26d1c45f
 
-value_members:
+attribute_value_members:
   metadata:
-    table_name: value_members
+    table_name: attribute_value_members
     columns:
       - id
       - value_id
diff --git a/migrations/20240313000000_create_val_members.sql b/migrations/20240313000000_create_val_members.sql
index 2bf0b0e568..9aebf5bdfa 100644
--- a/migrations/20240313000000_create_val_members.sql
+++ b/migrations/20240313000000_create_val_members.sql
@@ -1,7 +1,7 @@
 -- +goose Up
 -- +goose StatementBegin
 
-CREATE TABLE IF NOT EXISTS value_members
+CREATE TABLE IF NOT EXISTS attribute_value_members
 (
     id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
     value_id UUID NOT NULL REFERENCES attribute_values(id),
@@ -26,7 +26,7 @@ $$ language 'plpgsql';
 CREATE TRIGGER value_members_insert
     AFTER
         INSERT
-    ON value_members
+    ON attribute_value_members
     FOR EACH ROW
     EXECUTE PROCEDURE update_attribute_values_members();
 
@@ -47,7 +47,7 @@ $$ language 'plpgsql';
 CREATE TRIGGER value_members_delete
     AFTER
         DELETE
-    ON value_members
+    ON attribute_value_members
     FOR EACH ROW
     EXECUTE PROCEDURE delete_attribute_values_members();
 
@@ -58,9 +58,9 @@ RETURNS TRIGGER AS $$
 BEGIN
     IF (TG_OP = 'DELETE') THEN
         UPDATE attribute_values
-        SET members = array_remove(members, value_members.id)
-        FROM value_members
-        WHERE value_members.member_id = OLD.id;
+        SET members = array_remove(members, attribute_value_members.id)
+        FROM attribute_value_members
+        WHERE attribute_value_members.member_id = OLD.id;
     END IF;
     RETURN NULL;
 END
@@ -73,13 +73,13 @@ CREATE TRIGGER attribute_values_delete
     FOR EACH ROW
     EXECUTE PROCEDURE delete_attribute_values_members_on_attribute_value_delete();
 
--- trigger to update value_members when attribute_value is deleted
+-- trigger to update attribute_value_members when attribute_value is deleted
 CREATE OR REPLACE FUNCTION delete_value_members_on_attribute_value_delete()
 RETURNS TRIGGER AS $$
 BEGIN
     IF (TG_OP = 'DELETE') THEN
-        DELETE FROM value_members
-        WHERE value_members.value_id = OLD.id OR value_members.member_id = OLD.id;
+        DELETE FROM attribute_value_members
+        WHERE attribute_value_members.value_id = OLD.id OR attribute_value_members.member_id = OLD.id;
     END IF;
     RETURN NULL;
 END
@@ -92,12 +92,12 @@ CREATE TRIGGER attribute_values_delete_value_members
     FOR EACH ROW
     EXECUTE PROCEDURE delete_value_members_on_attribute_value_delete();
 
--- trigger to update value_members when attribute_value is updated
+-- trigger to update attribute_value_members when attribute_value is updated
 CREATE OR REPLACE FUNCTION update_value_members_on_attribute_value_update()
 RETURNS TRIGGER AS $$
 BEGIN
     IF (TG_OP = 'UPDATE') THEN
-        UPDATE value_members
+        UPDATE attribute_value_members
         SET value_id = NEW.id
         WHERE value_id = OLD.id;
     END IF;
@@ -117,5 +117,5 @@ CREATE TRIGGER attribute_values_update_value_members
 -- +goose Down
 
 -- +goose StatementBegin
-DROP TABLE IF EXISTS value_members;
+DROP TABLE IF EXISTS attribute_value_members;
 -- +goose StatementEnd
diff --git a/services/policy/db/policy.go b/services/policy/db/policy.go
index 52b8d66d7c..b56440b8ae 100644
--- a/services/policy/db/policy.go
+++ b/services/policy/db/policy.go
@@ -18,7 +18,7 @@ type PolicyDbClient struct {
 var (
 	TableAttributes                    = "attribute_definitions"
 	TableAttributeValues               = "attribute_values"
-	TableValueMembers                  = "value_members"
+	TableValueMembers                  = "attribute_value_members"
 	TableNamespaces                    = "attribute_namespaces"
 	TableAttrFqn                       = "attribute_fqns"
 	TableAttributeKeyAccessGrants      = "attribute_definition_key_access_grants"

From df41d3b475896a6144e39d3848e1968b58c2c4d3 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 11:15:17 -0400
Subject: [PATCH 24/31] remove db triggers

---
 .../20240313000000_create_val_members.sql     | 103 ------------------
 1 file changed, 103 deletions(-)

diff --git a/migrations/20240313000000_create_val_members.sql b/migrations/20240313000000_create_val_members.sql
index 9aebf5bdfa..0e88e7615f 100644
--- a/migrations/20240313000000_create_val_members.sql
+++ b/migrations/20240313000000_create_val_members.sql
@@ -9,109 +9,6 @@ CREATE TABLE IF NOT EXISTS attribute_value_members
     UNIQUE (value_id, member_id)
 );
 
--- trigger to update attribute_values.members when value_member is added
-CREATE OR REPLACE FUNCTION update_attribute_values_members()
-RETURNS TRIGGER AS $$
-BEGIN
-    IF (TG_OP = 'INSERT') THEN
-        UPDATE attribute_values
-        SET members = array_append(members, NEW.id)
-        WHERE id = NEW.value_id;
-        -- AND NEW.id <> ALL(members);
-    END IF;
-    RETURN NULL;
-END
-$$ language 'plpgsql';
-
-CREATE TRIGGER value_members_insert
-    AFTER
-        INSERT
-    ON attribute_value_members
-    FOR EACH ROW
-    EXECUTE PROCEDURE update_attribute_values_members();
-
-
--- trigger to update attribute_values.members when value_member is deleted
-CREATE OR REPLACE FUNCTION delete_attribute_values_members()
-RETURNS TRIGGER AS $$
-BEGIN
-    IF (TG_OP = 'DELETE') THEN
-        UPDATE attribute_values
-        SET members = array_remove(members, OLD.id)
-        WHERE id = OLD.value_id;
-    END IF;
-    RETURN NULL;
-END
-$$ language 'plpgsql';
-
-CREATE TRIGGER value_members_delete
-    AFTER
-        DELETE
-    ON attribute_value_members
-    FOR EACH ROW
-    EXECUTE PROCEDURE delete_attribute_values_members();
-
-
--- trigger to update attribute_values.members when attribute_value is deleted
-CREATE OR REPLACE FUNCTION delete_attribute_values_members_on_attribute_value_delete()
-RETURNS TRIGGER AS $$
-BEGIN
-    IF (TG_OP = 'DELETE') THEN
-        UPDATE attribute_values
-        SET members = array_remove(members, attribute_value_members.id)
-        FROM attribute_value_members
-        WHERE attribute_value_members.member_id = OLD.id;
-    END IF;
-    RETURN NULL;
-END
-$$ language 'plpgsql';
-
-CREATE TRIGGER attribute_values_delete
-    AFTER
-        DELETE
-    ON attribute_values
-    FOR EACH ROW
-    EXECUTE PROCEDURE delete_attribute_values_members_on_attribute_value_delete();
-
--- trigger to update attribute_value_members when attribute_value is deleted
-CREATE OR REPLACE FUNCTION delete_value_members_on_attribute_value_delete()
-RETURNS TRIGGER AS $$
-BEGIN
-    IF (TG_OP = 'DELETE') THEN
-        DELETE FROM attribute_value_members
-        WHERE attribute_value_members.value_id = OLD.id OR attribute_value_members.member_id = OLD.id;
-    END IF;
-    RETURN NULL;
-END
-$$ language 'plpgsql';
-
-CREATE TRIGGER attribute_values_delete_value_members
-    AFTER
-        DELETE
-    ON attribute_values
-    FOR EACH ROW
-    EXECUTE PROCEDURE delete_value_members_on_attribute_value_delete();
-
--- trigger to update attribute_value_members when attribute_value is updated
-CREATE OR REPLACE FUNCTION update_value_members_on_attribute_value_update()
-RETURNS TRIGGER AS $$
-BEGIN
-    IF (TG_OP = 'UPDATE') THEN
-        UPDATE attribute_value_members
-        SET value_id = NEW.id
-        WHERE value_id = OLD.id;
-    END IF;
-    RETURN NULL;
-END
-$$ language 'plpgsql';
-
-CREATE TRIGGER attribute_values_update_value_members
-    AFTER
-        UPDATE
-    ON attribute_values
-    FOR EACH ROW
-    EXECUTE PROCEDURE update_value_members_on_attribute_value_update();
-
 -- +goose StatementEnd
 
 -- +goose Down

From ad5df0d760799ae6bffe743b60be1515d4257fe7 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 11:19:43 -0400
Subject: [PATCH 25/31] update ERD

---
 migrations/20240313000000_create_val_members.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/migrations/20240313000000_create_val_members.md b/migrations/20240313000000_create_val_members.md
index 5075c8796a..592914c41a 100644
--- a/migrations/20240313000000_create_val_members.md
+++ b/migrations/20240313000000_create_val_members.md
@@ -14,7 +14,6 @@ erDiagram
         uuid         namespace_id            FK
         uuid         attribute_definition_id FK
         varchar      value
-        uuid[]       members                 FK "Optional grouping of values"
         jsonb        metadata
         compIdx      comp_key                UK "ns_id + ad_id + value"
         bool         active

From adc0ff1c63b1cca504b1b392c4dcdef6bc5fde9a Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 11:30:18 -0400
Subject: [PATCH 26/31] remove set

---
 internal/set/set.go                    | 103 -------------------------
 services/policy/db/attribute_values.go |  61 ++++++---------
 2 files changed, 23 insertions(+), 141 deletions(-)
 delete mode 100644 internal/set/set.go

diff --git a/internal/set/set.go b/internal/set/set.go
deleted file mode 100644
index 8493f61e8c..0000000000
--- a/internal/set/set.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package set
-
-type Set struct {
-	set map[interface{}]struct{}
-}
-
-func NewSet() *Set {
-	return &Set{set: make(map[interface{}]struct{})}
-}
-
-func (s *Set) Add(i interface{}) {
-	s.set[i] = struct{}{}
-}
-
-func (s *Set) Remove(i interface{}) {
-	delete(s.set, i)
-}
-
-func (s *Set) Contains(i interface{}) bool {
-	_, ok := s.set[i]
-	return ok
-}
-
-func (s *Set) Len() int {
-	return len(s.set)
-}
-
-func (s *Set) ToSlice() []interface{} {
-	slice := make([]interface{}, 0, len(s.set))
-	for i := range s.set {
-		slice = append(slice, i)
-	}
-	return slice
-}
-
-func (s *Set) Each(f func(interface{})) {
-	for i := range s.set {
-		f(i)
-	}
-}
-
-func (s *Set) Iter() <-chan interface{} {
-	ch := make(chan interface{})
-	go func() {
-		for i := range s.set {
-			ch <- i
-		}
-		close(ch)
-	}()
-	return ch
-}
-
-func (s *Set) Union(other *Set) *Set {
-	union := NewSet()
-	for i := range s.set {
-		union.Add(i)
-	}
-	for i := range other.set {
-		union.Add(i)
-	}
-	return union
-}
-
-func (s *Set) Intersect(other *Set) *Set {
-	intersect := NewSet()
-	for i := range s.set {
-		if other.Contains(i) {
-			intersect.Add(i)
-		}
-	}
-	return intersect
-}
-
-func (s *Set) Difference(other *Set) *Set {
-	difference := NewSet()
-	for i := range s.set {
-		if !other.Contains(i) {
-			difference.Add(i)
-		}
-	}
-	return difference
-}
-
-func (s *Set) IsSubset(other *Set) bool {
-	for i := range s.set {
-		if !other.Contains(i) {
-			return false
-		}
-	}
-	return true
-}
-
-func (s *Set) IsSuperset(other *Set) bool {
-	return other.IsSubset(s)
-}
-
-func (s *Set) Equal(other *Set) bool {
-	return s.IsSubset(other) && s.IsSuperset(other)
-}
-
-func (s *Set) Clear() {
-	s.set = make(map[interface{}]struct{})
-}
diff --git a/services/policy/db/attribute_values.go b/services/policy/db/attribute_values.go
index 2bf8bed84e..267e848b67 100644
--- a/services/policy/db/attribute_values.go
+++ b/services/policy/db/attribute_values.go
@@ -9,7 +9,6 @@ import (
 	sq "github.com/Masterminds/squirrel"
 	"github.com/jackc/pgx/v5"
 	"github.com/opentdf/platform/internal/db"
-	"github.com/opentdf/platform/internal/set"
 	"github.com/opentdf/platform/protocol/go/common"
 	"github.com/opentdf/platform/protocol/go/policy"
 	"github.com/opentdf/platform/protocol/go/policy/attributes"
@@ -207,23 +206,6 @@ func (c PolicyDbClient) CreateAttributeValue(ctx context.Context, attributeId st
 	return rV, nil
 }
 
-// func getMemberSql(id string) (string, []interface{}, error) {
-// 	t := Tables.ValueMembers
-// 	fields := []string{
-// 		t.Field("id"),
-// 		t.Field("value_id"),
-// 		t.Field("member_id"),
-// 	}
-
-// 	sb := db.NewStatementBuilder().
-// 		Select(fields...).
-// 		From(t.Name())
-
-// 	return sb.
-// 		Where(sq.Eq{t.Field("id"): id}).
-// 		ToSql()
-// }
-
 func getAttributeValueSql(id string, opts attributeValueSelectOptions) (string, []interface{}, error) {
 	t := Tables.AttributeValues
 	fqnT := Tables.AttrFqn
@@ -466,22 +448,35 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 	if err := c.Exec(ctx, sql, args); err != nil {
 		return nil, err
 	}
-	prevMembersSet := set.NewSet()
+	prevMembersSet := map[string]bool{}
+
 	for _, member := range prev.Members {
-		prevMembersSet.Add(member.Id)
+		prevMembersSet[member.Id] = true
 	}
 
-	membersSet := set.NewSet()
+	membersSet := map[string]bool{}
 	for _, member := range r.Members {
-		membersSet.Add(member)
+		membersSet[member] = true
+	}
+
+	toRemove := map[string]bool{}
+	toAdd := map[string]bool{}
+
+	for member := range prevMembersSet {
+		if _, ok := membersSet[member]; !ok {
+			toRemove[member] = true
+		}
 	}
 
-	toRemove := prevMembersSet.Difference(membersSet).ToSlice()
-	toAdd := membersSet.Difference(prevMembersSet).ToSlice()
+	for member := range membersSet {
+		if _, ok := prevMembersSet[member]; !ok {
+			toAdd[member] = true
+		}
+	}
 
 	// Remove members
-	for _, member := range toRemove {
-		sql, args, err := removeMemberSql(r.Id, member.(string))
+	for member := range toRemove {
+		sql, args, err := removeMemberSql(r.Id, member)
 		if err != nil {
 			return nil, err
 		}
@@ -490,9 +485,8 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 		}
 	}
 
-	// Add members
-	for _, member := range toAdd {
-		sql, args, err := addMemberSql(r.Id, member.(string))
+	for member := range toAdd {
+		sql, args, err := addMemberSql(r.Id, member)
 		if err != nil {
 			return nil, err
 		}
@@ -501,15 +495,6 @@ func (c PolicyDbClient) UpdateAttributeValue(ctx context.Context, r *attributes.
 		}
 	}
 
-	// var members []*policy.Value
-	// for _, member := range r.Members {
-	// 	attr, err := c.GetAttributeValue(ctx, member)
-	// 	if err != nil {
-	// 		return nil, err
-	// 	}
-	// 	members = append(members, attr)
-	// }
-
 	// Update FQN
 	c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueId: r.Id})
 

From 2c349d5422eafe3c55916ebb294493ef31f35008 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 12:27:15 -0400
Subject: [PATCH 27/31] add value member test to resource mapping

---
 integration/attribute_values_test.go   | 21 ++++++++++++++-------
 integration/resource_mappings_test.go  | 13 ++++++++++++-
 internal/fixtures/policy_fixtures.yaml |  5 +++++
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/integration/attribute_values_test.go b/integration/attribute_values_test.go
index 1ec6cc47e0..c6f252833a 100644
--- a/integration/attribute_values_test.go
+++ b/integration/attribute_values_test.go
@@ -138,7 +138,18 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_NoMembers_Succeeds() {
 	assert.Equal(s.T(), len(createdValue.Members), len(got.Members))
 	assert.EqualValues(s.T(), createdValue.Metadata.Labels, got.Metadata.Labels)
 }
-
+func equalMembers(t *testing.T, v1 *policy.Value, v2 *policy.Value, withFqn bool) {
+	m1 := v1.Members
+	m2 := v2.Members
+	for idx := range m1 {
+		assert.Equal(t, m1[idx].Id, m2[idx].Id)
+		assert.Equal(t, m1[idx].Value, m2[idx].Value)
+		if withFqn {
+			assert.Equal(t, m1[idx].Fqn, m2[idx].Fqn)
+		}
+		assert.Equal(t, m1[idx].Active.Value, m2[idx].Active.Value)
+	}
+}
 func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithMembers_Succeeds() {
 	attrDef := s.f.GetAttributeKey("example.net/attr/attr1")
 	metadata := &common.MetadataMutable{
@@ -166,13 +177,9 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithMembers_Succeeds()
 	assert.Equal(s.T(), createdValue.Value, got.Value)
 	assert.EqualValues(s.T(), createdValue.Metadata.Labels, got.Metadata.Labels)
 	assert.Equal(s.T(), len(createdValue.Members), len(got.Members))
+
 	assert.True(s.T(), len(got.Members) > 0)
-	for idx, member := range got.Members {
-		assert.Equal(s.T(), member.Id, createdValue.Members[idx].Id)
-		assert.Equal(s.T(), member.Value, createdValue.Members[idx].Value)
-		assert.Equal(s.T(), member.Fqn, createdValue.Members[idx].Fqn)
-		assert.Equal(s.T(), member.Active.Value, createdValue.Members[idx].Active.Value)
-	}
+	equalMembers(s.T(), createdValue, got, true)
 }
 
 func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidAttributeId_Fails() {
diff --git a/integration/resource_mappings_test.go b/integration/resource_mappings_test.go
index bf7eb11507..267d230879 100644
--- a/integration/resource_mappings_test.go
+++ b/integration/resource_mappings_test.go
@@ -43,6 +43,7 @@ func (s *ResourceMappingsSuite) getResourceMappingFixtures() []fixtures.FixtureD
 		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value1"),
 		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value2"),
 		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value3"),
+		s.f.GetResourceMappingKey("resource_mapping_to_attribute_value4"),
 	}
 }
 
@@ -115,13 +116,23 @@ func (s *ResourceMappingsSuite) Test_ListResourceMappings() {
 func (s *ResourceMappingsSuite) Test_GetResourceMapping() {
 	// make sure we can get all fixtures
 	testData := s.getResourceMappingFixtures()
-	for _, testMapping := range testData {
+	testedMembers := false
+	for idx, testMapping := range testData {
 		mapping, err := s.db.PolicyClient.GetResourceMapping(s.ctx, testMapping.Id)
 		assert.Nil(s.T(), err)
 		assert.NotNil(s.T(), mapping)
 		assert.Equal(s.T(), testMapping.Id, mapping.Id)
 		assert.Equal(s.T(), testMapping.AttributeValueId, mapping.AttributeValue.Id)
 		assert.Equal(s.T(), testMapping.Terms, mapping.Terms)
+		av, err := s.db.PolicyClient.GetAttributeValue(s.ctx, testMapping.AttributeValueId)
+		assert.Nil(s.T(), err)
+		if len(av.Members) > 0 {
+			testedMembers = true
+		}
+		if idx == len(testData)-1 {
+			assert.True(s.T(), testedMembers, "expected to test at least one attribute value member")
+		}
+		equalMembers(s.T(), av, mapping.AttributeValue, false)
 	}
 }
 
diff --git a/internal/fixtures/policy_fixtures.yaml b/internal/fixtures/policy_fixtures.yaml
index f0c336d406..b2deeb7302 100644
--- a/internal/fixtures/policy_fixtures.yaml
+++ b/internal/fixtures/policy_fixtures.yaml
@@ -402,6 +402,11 @@ resource_mappings:
       attribute_value_id: 04bd2657-de10-46bc-a88f-5d687de4816b
       terms:
         - helloworld
+    resource_mapping_to_attribute_value4:
+      id: f99d1c97-ad8a-40c8-8148-6539764e2743
+      attribute_value_id: 2fe8dea1-3555-498c-afe9-99724f35f3d3
+      terms:
+        - with_members
 
 ##
 # KAS Registry (key access server registry)

From b4d590b4412793921d43c73314060088701b014c Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 12:44:10 -0400
Subject: [PATCH 28/31] add value member test to subject mapping

---
 integration/attribute_values_test.go | 7 +++++++
 integration/subject_mappings_test.go | 8 +++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/integration/attribute_values_test.go b/integration/attribute_values_test.go
index c6f252833a..481e52b532 100644
--- a/integration/attribute_values_test.go
+++ b/integration/attribute_values_test.go
@@ -3,6 +3,7 @@ package integration
 import (
 	"context"
 	"log/slog"
+	"sort"
 	"testing"
 
 	"github.com/opentdf/platform/internal/db"
@@ -141,6 +142,12 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_NoMembers_Succeeds() {
 func equalMembers(t *testing.T, v1 *policy.Value, v2 *policy.Value, withFqn bool) {
 	m1 := v1.Members
 	m2 := v2.Members
+	sort.Slice(m1, func(x, y int) bool {
+		return m1[x].Id < m1[y].Id
+	})
+	sort.Slice(m2, func(x, y int) bool {
+		return m2[x].Id < m2[y].Id
+	})
 	for idx := range m1 {
 		assert.Equal(t, m1[idx].Id, m2[idx].Id)
 		assert.Equal(t, m1[idx].Value, m2[idx].Value)
diff --git a/integration/subject_mappings_test.go b/integration/subject_mappings_test.go
index f9d0433106..4bc538a446 100644
--- a/integration/subject_mappings_test.go
+++ b/integration/subject_mappings_test.go
@@ -346,7 +346,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_NonExistentSubjectCondit
 }
 
 func (s *SubjectMappingsSuite) TestGetSubjectMapping() {
-	fixture := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute3")
+	fixture := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute2")
 
 	sm, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, fixture.Id)
 	assert.Nil(s.T(), err)
@@ -367,6 +367,12 @@ func (s *SubjectMappingsSuite) TestGetSubjectMapping() {
 			assert.Equal(s.T(), "custom:\""+fixture.Actions[i].Custom+"\"", a.String())
 		}
 	}
+	got, err := s.db.PolicyClient.GetAttributeValue(s.ctx, fixture.AttributeValueId)
+	assert.Nil(s.T(), err)
+	assert.NotNil(s.T(), got)
+	assert.Equal(s.T(), fixture.AttributeValueId, got.Id)
+	assert.True(s.T(), len(got.Members) > 0)
+	equalMembers(s.T(), got, sm.AttributeValue, false)
 }
 
 func (s *SubjectMappingsSuite) TestGetSubjectMapping_NonExistentId_Fails() {

From ef02242c33329510791dad52c1aed7a075fc23c9 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 13:02:52 -0400
Subject: [PATCH 29/31] add tests for value member foreign key violations and
 invalid uuids

---
 integration/attribute_values_test.go | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/integration/attribute_values_test.go b/integration/attribute_values_test.go
index 481e52b532..3f17cad61f 100644
--- a/integration/attribute_values_test.go
+++ b/integration/attribute_values_test.go
@@ -199,6 +199,34 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidAttributeId_
 	assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation)
 }
 
+func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidMember_Fails() {
+	attrDef := s.f.GetAttributeKey("example.net/attr/attr1")
+	metadata := &common.MetadataMutable{
+		Labels: map[string]string{
+			"name": "testing create with members",
+		},
+	}
+
+	value := &attributes.CreateAttributeValueRequest{
+		Value: "value3",
+		Members: []string{
+			nonExistentAttributeValueUuid,
+		},
+		Metadata: metadata,
+	}
+	createdValue, err := s.db.PolicyClient.CreateAttributeValue(s.ctx, attrDef.Id, value)
+	assert.Nil(s.T(), createdValue)
+	assert.NotNil(s.T(), err)
+	assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation)
+
+	attrDef = s.f.GetAttributeKey("example.net/attr/attr2")
+	value.Members[0] = "not a uuid"
+	createdValue, err = s.db.PolicyClient.CreateAttributeValue(s.ctx, attrDef.Id, value)
+	assert.Nil(s.T(), createdValue)
+	assert.NotNil(s.T(), err)
+	assert.ErrorIs(s.T(), err, db.ErrUuidInvalid)
+}
+
 func (s *AttributeValuesSuite) Test_UpdateAttributeValue() {
 	fixedLabel := "fixed label"
 	updateLabel := "update label"

From 8234843b5cfaedd5cb890002f763abbd50ff94e3 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 13:11:26 -0400
Subject: [PATCH 30/31] add unique constraint violation test

---
 integration/attribute_values_test.go | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/integration/attribute_values_test.go b/integration/attribute_values_test.go
index 3f17cad61f..f1c8679ce5 100644
--- a/integration/attribute_values_test.go
+++ b/integration/attribute_values_test.go
@@ -187,6 +187,13 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithMembers_Succeeds()
 
 	assert.True(s.T(), len(got.Members) > 0)
 	equalMembers(s.T(), createdValue, got, true)
+
+	// test uniqueness
+	createdValue, err = s.db.PolicyClient.CreateAttributeValue(s.ctx, attrDef.Id, value)
+	assert.NotNil(s.T(), err)
+	assert.Nil(s.T(), createdValue)
+	println(err.Error())
+	assert.ErrorIs(s.T(), err, db.ErrUniqueConstraintViolation)
 }
 
 func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidAttributeId_Fails() {
@@ -200,7 +207,7 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidAttributeId_
 }
 
 func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidMember_Fails() {
-	attrDef := s.f.GetAttributeKey("example.net/attr/attr1")
+	attrDef := s.f.GetAttributeKey("example.net/attr/attr2")
 	metadata := &common.MetadataMutable{
 		Labels: map[string]string{
 			"name": "testing create with members",
@@ -219,7 +226,7 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithInvalidMember_Fails
 	assert.NotNil(s.T(), err)
 	assert.ErrorIs(s.T(), err, db.ErrForeignKeyViolation)
 
-	attrDef = s.f.GetAttributeKey("example.net/attr/attr2")
+	attrDef = s.f.GetAttributeKey("example.net/attr/attr3")
 	value.Members[0] = "not a uuid"
 	createdValue, err = s.db.PolicyClient.CreateAttributeValue(s.ctx, attrDef.Id, value)
 	assert.Nil(s.T(), createdValue)

From 2f3d6e8cf652c3ffa72b99e74edb392418283f67 Mon Sep 17 00:00:00 2001
From: Krish Suchak 
Date: Thu, 14 Mar 2024 13:29:21 -0400
Subject: [PATCH 31/31] remove debug statement

---
 integration/attribute_values_test.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/integration/attribute_values_test.go b/integration/attribute_values_test.go
index f1c8679ce5..8e6c66fa5e 100644
--- a/integration/attribute_values_test.go
+++ b/integration/attribute_values_test.go
@@ -192,7 +192,6 @@ func (s *AttributeValuesSuite) Test_CreateAttributeValue_WithMembers_Succeeds()
 	createdValue, err = s.db.PolicyClient.CreateAttributeValue(s.ctx, attrDef.Id, value)
 	assert.NotNil(s.T(), err)
 	assert.Nil(s.T(), createdValue)
-	println(err.Error())
 	assert.ErrorIs(s.T(), err, db.ErrUniqueConstraintViolation)
 }