From 84a5412c4520cdd92baae7bb18f716c212ce10f6 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Wed, 14 Feb 2024 08:32:00 -0500 Subject: [PATCH 01/14] feat: adds allFlagKeys to provider metadata Signed-off-by: Max VelDink --- specification.json | 22 ++++++++++++++++++++++ specification/sections/02-providers.md | 16 ++++++++++++++++ specification/types.md | 12 ++++++++++++ 3 files changed, 50 insertions(+) diff --git a/specification.json b/specification.json index 1a3b3d31..1e330e18 100644 --- a/specification.json +++ b/specification.json @@ -358,6 +358,28 @@ "RFC 2119 keyword": "MUST", "children": [] }, + { + "id": "Requirement 2.1.2", + "machine_id": "requirement_2_1_2", + "content": "The provider `metadata` member or accessor MAY define an `allFlagKeys` field or accessor of type collection of strings, which identifies all available flag keys in the provider.", + "RFC 2119 keyword": "MAY", + "children": [] + }, + { + "id": "Condition 2.1.3", + "machine_id": "condition_2_1_3", + "content": "The implementing language has an asynchronous support.", + "RFC 2119 keyword": null, + "children": [ + { + "id": "Conditional Requirement 2.1.3.1", + "machine_id": "conditional_requirement_2_1_3_1", + "content": "The accessor for `allFlagKeys` SHOULD be asynchronous.", + "RFC 2119 keyword": "SHOULD", + "children": [] + } + ] + }, { "id": "Requirement 2.2.1", "machine_id": "requirement_2_2_1", diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index b540cdb3..1d1c4da4 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -26,6 +26,22 @@ Providers are the "translator" between the flag evaluation calls made in applica provider.getMetadata().getName(); // "my-custom-provider" ``` +#### Requirement 2.1.2 + +> The provider `metadata` member or accessor **MAY** define an `allFlagKeys` field or accessor of type collection of strings, which identifies all available flag keys in the provider. + +```typescript +provider.getMetadata().getAllFlagKeys(); // ['featureA', 'featureB'] +``` + +#### Condition 2.1.3 + +> The implementing language has an asynchronous support. + +##### Conditional Requirement 2.1.3.1 + +> The accessor for `allFlagKeys` **SHOULD** be asynchronous. + ### 2.2 Flag Value Resolution `Providers` are implementations of the `feature provider` interface, which may wrap vendor SDKs, REST API clients, or otherwise resolve flag values from the runtime environment. diff --git a/specification/types.md b/specification/types.md index bb7d340f..db899e91 100644 --- a/specification/types.md +++ b/specification/types.md @@ -26,6 +26,10 @@ A numeric value of unspecified type or size. Implementation languages may furthe Structured data, presented however is idiomatic in the implementation language, such as JSON or YAML. +### Collection + +A list or series of similar data types, presented however is idiomatic in the implementation language. + ### Datetime A language primitive for representing a date and time, optionally including timezone information. If no timezone is specified, the date and time will be treated as UTC. @@ -125,6 +129,14 @@ A structure which supports definition of arbitrary properties, with keys of type This structure is populated by a provider for use by an [Application Author](./glossary.md#application-author) via the [Evaluation API](./glossary.md#evaluation-api) or an [Application Integrator](./glossary.md#application-integrator) via [hooks](./sections/04-hooks.md). +### Provider Metadata + +A structure which carries information about the provider. +In addition to the defined metadata fields below, arbitrary information can be stored here unique to the provider. + +`name` is a required key with a string value. +`allFlagKeys` is an optional key with a collection of string value. + ### Provider Status An enumeration of possible provider states. From 129712e28d5f15250b6ea55e18f734c164ead2ee Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Thu, 15 Feb 2024 09:28:57 -0500 Subject: [PATCH 02/14] docs: Return flag metadata instead of just flag keys Signed-off-by: Max VelDink --- specification.json | 4 ++-- specification/sections/02-providers.md | 6 +++--- specification/types.md | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/specification.json b/specification.json index 1e330e18..34fcf5bc 100644 --- a/specification.json +++ b/specification.json @@ -361,7 +361,7 @@ { "id": "Requirement 2.1.2", "machine_id": "requirement_2_1_2", - "content": "The provider `metadata` member or accessor MAY define an `allFlagKeys` field or accessor of type collection of strings, which identifies all available flag keys in the provider.", + "content": "The provider `metadata` member or accessor MAY define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md", "RFC 2119 keyword": "MAY", "children": [] }, @@ -374,7 +374,7 @@ { "id": "Conditional Requirement 2.1.3.1", "machine_id": "conditional_requirement_2_1_3_1", - "content": "The accessor for `allFlagKeys` SHOULD be asynchronous.", + "content": "The accessor for `allFlagMetadata` SHOULD be asynchronous.", "RFC 2119 keyword": "SHOULD", "children": [] } diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 1d1c4da4..0bdf3b93 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -28,10 +28,10 @@ provider.getMetadata().getName(); // "my-custom-provider" #### Requirement 2.1.2 -> The provider `metadata` member or accessor **MAY** define an `allFlagKeys` field or accessor of type collection of strings, which identifies all available flag keys in the provider. +> The provider `metadata` member or accessor **MAY** define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md#flag-metadata), which identifies all available flag keys in the provider. ```typescript -provider.getMetadata().getAllFlagKeys(); // ['featureA', 'featureB'] +provider.getMetadata().getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] ``` #### Condition 2.1.3 @@ -40,7 +40,7 @@ provider.getMetadata().getAllFlagKeys(); // ['featureA', 'featureB'] ##### Conditional Requirement 2.1.3.1 -> The accessor for `allFlagKeys` **SHOULD** be asynchronous. +> The accessor for `allFlagMetadata` **SHOULD** be asynchronous. ### 2.2 Flag Value Resolution diff --git a/specification/types.md b/specification/types.md index db899e91..51966914 100644 --- a/specification/types.md +++ b/specification/types.md @@ -127,6 +127,9 @@ A structure containing the following fields: A structure which supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. +`key` is a required property with a value of `string`. +`type` is a required property with a `string` value of either `boolean`, `string`, `number`, or `structure`. + This structure is populated by a provider for use by an [Application Author](./glossary.md#application-author) via the [Evaluation API](./glossary.md#evaluation-api) or an [Application Integrator](./glossary.md#application-integrator) via [hooks](./sections/04-hooks.md). ### Provider Metadata From ec843bae91951e03336d5d32ddd358df62e1ffaf Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Fri, 16 Feb 2024 21:39:12 -0500 Subject: [PATCH 03/14] docs: Make type optional and clarify intention Signed-off-by: Max VelDink --- specification/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/types.md b/specification/types.md index 51966914..ba245bc8 100644 --- a/specification/types.md +++ b/specification/types.md @@ -128,7 +128,7 @@ A structure containing the following fields: A structure which supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. `key` is a required property with a value of `string`. -`type` is a required property with a `string` value of either `boolean`, `string`, `number`, or `structure`. +`type` is an optional property with a `string` value indicating which client resolution method should be used to resolve the flag key. This structure is populated by a provider for use by an [Application Author](./glossary.md#application-author) via the [Evaluation API](./glossary.md#evaluation-api) or an [Application Integrator](./glossary.md#application-integrator) via [hooks](./sections/04-hooks.md). From 906ed81a27e305e2d4ad8d010f2039d8f0ddfadf Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Wed, 21 Feb 2024 12:34:54 -0500 Subject: [PATCH 04/14] refactor: Move allFlagMetadata to provider directly Signed-off-by: Max VelDink --- specification/sections/02-providers.md | 4 ++-- specification/types.md | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 0bdf3b93..08eca6bd 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -28,10 +28,10 @@ provider.getMetadata().getName(); // "my-custom-provider" #### Requirement 2.1.2 -> The provider `metadata` member or accessor **MAY** define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md#flag-metadata), which identifies all available flag keys in the provider. +> The provider **MAY** define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md#flag-metadata), which identifies all available flag keys in the provider. ```typescript -provider.getMetadata().getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] +provider.getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] ``` #### Condition 2.1.3 diff --git a/specification/types.md b/specification/types.md index ba245bc8..23619ed1 100644 --- a/specification/types.md +++ b/specification/types.md @@ -138,7 +138,6 @@ A structure which carries information about the provider. In addition to the defined metadata fields below, arbitrary information can be stored here unique to the provider. `name` is a required key with a string value. -`allFlagKeys` is an optional key with a collection of string value. ### Provider Status From 72b496f1f283ffb042eee1ac181bd627c965cdb7 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Wed, 21 Feb 2024 12:39:59 -0500 Subject: [PATCH 05/14] feat: Add allFlagMetadata to client Signed-off-by: Max VelDink --- specification.json | 9 ++++++++- specification/sections/01-flag-evaluation.md | 12 +++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/specification.json b/specification.json index 34fcf5bc..3cffa1f0 100644 --- a/specification.json +++ b/specification.json @@ -84,6 +84,13 @@ "RFC 2119 keyword": "MUST", "children": [] }, + { + "id": "Requirement 1.2.3", + "machine_id": "requirement_1_2_3", + "content": "The client interface MUST define a `allFlagMetadata` member or accessor, returning a collection of flag metadata from the provider.", + "RFC 2119 keyword": "MUST", + "children": [] + }, { "id": "Condition 1.3.1", "machine_id": "condition_1_3_1", @@ -361,7 +368,7 @@ { "id": "Requirement 2.1.2", "machine_id": "requirement_2_1_2", - "content": "The provider `metadata` member or accessor MAY define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md", + "content": "The provider MAY define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md", "RFC 2119 keyword": "MAY", "children": [] }, diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index db40c13f..0d88c1fe 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -65,7 +65,7 @@ This function not only sets the provider, but ensures that the provider is ready // default provider OpenFeatureAPI.getInstance().setProviderAndWait(myprovider); // this method blocks until the provider is ready or in error // client uses the default provider -Client client = OpenFeatureAPI.getInstance().getClient(); +Client client = OpenFeatureAPI.getInstance().getClient(); // provider associated with domain-1 OpenFeatureAPI.getInstance().setProviderAndWait('domain-1', myprovider); // this method blocks until the provider is ready or in error @@ -171,6 +171,16 @@ client.getMetadata().getDomain(); // "domain-1" In previous drafts, this property was called `name`. For backwards compatibility, implementations should consider `name` an alias to `domain`. +#### Requirement 1.2.3 + +> The client interface **MUST** define a `allFlagMetadata` member or accessor, returning a collection of flag metadata from the provider. + +```typescript +client.getAllFlagMetadata() // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] +``` + +This may return an empty collection if the provider does not implement the `allFlagMetadata` member or accessor. + ### 1.3. Flag Evaluation [![hardening](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening) From fba1a6abd211831918ffac6fd12f214152200413 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Thu, 22 Feb 2024 05:33:48 -0500 Subject: [PATCH 06/14] fix: Don't use markdown in specification Signed-off-by: Max VelDink --- specification.json | 2 +- specification/sections/02-providers.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specification.json b/specification.json index 3cffa1f0..1a35eccd 100644 --- a/specification.json +++ b/specification.json @@ -368,7 +368,7 @@ { "id": "Requirement 2.1.2", "machine_id": "requirement_2_1_2", - "content": "The provider MAY define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md", + "content": "The provider MAY define an `allFlagMetadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider.", "RFC 2119 keyword": "MAY", "children": [] }, diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 08eca6bd..f73344fe 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -28,7 +28,7 @@ provider.getMetadata().getName(); // "my-custom-provider" #### Requirement 2.1.2 -> The provider **MAY** define an `allFlagMetadata` field or accessor of type collection of [flag_metadata](../types.md#flag-metadata), which identifies all available flag keys in the provider. +> The provider **MAY** define an `allFlagMetadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider. ```typescript provider.getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] From fb4354519d30fe17d95da8b083a3d39ab4e8d922 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Mon, 26 Feb 2024 14:27:20 -0500 Subject: [PATCH 07/14] docs: Change async callout to non-normative Signed-off-by: Max VelDink --- specification.json | 15 --------------- specification/sections/02-providers.md | 8 +------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/specification.json b/specification.json index 1a35eccd..cb69d2ec 100644 --- a/specification.json +++ b/specification.json @@ -372,21 +372,6 @@ "RFC 2119 keyword": "MAY", "children": [] }, - { - "id": "Condition 2.1.3", - "machine_id": "condition_2_1_3", - "content": "The implementing language has an asynchronous support.", - "RFC 2119 keyword": null, - "children": [ - { - "id": "Conditional Requirement 2.1.3.1", - "machine_id": "conditional_requirement_2_1_3_1", - "content": "The accessor for `allFlagMetadata` SHOULD be asynchronous.", - "RFC 2119 keyword": "SHOULD", - "children": [] - } - ] - }, { "id": "Requirement 2.2.1", "machine_id": "requirement_2_2_1", diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index f73344fe..b69a87c4 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -34,13 +34,7 @@ provider.getMetadata().getName(); // "my-custom-provider" provider.getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] ``` -#### Condition 2.1.3 - -> The implementing language has an asynchronous support. - -##### Conditional Requirement 2.1.3.1 - -> The accessor for `allFlagMetadata` **SHOULD** be asynchronous. +For some providers, fetching all flags is an expensive operation. If there is language support, consider implementing this as an asynchronous operation. ### 2.2 Flag Value Resolution From 163579e205ab65d00bcca76f2e8665f12faa1817 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Mon, 26 Feb 2024 14:39:13 -0500 Subject: [PATCH 08/14] docs: Use null value on client if not implemented on provider Signed-off-by: Max VelDink --- specification/sections/01-flag-evaluation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index 0d88c1fe..3d229519 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -179,7 +179,7 @@ For backwards compatibility, implementations should consider `name` an alias to client.getAllFlagMetadata() // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] ``` -This may return an empty collection if the provider does not implement the `allFlagMetadata` member or accessor. +This may return a language-idiomatic way of describing the absence of a value if the provider does not implement the `allFlagMetadata` member or accessor. ### 1.3. Flag Evaluation From 828af47e7190139e7141f8fe6c0c54fe14bbdca3 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Mon, 26 Feb 2024 14:55:35 -0500 Subject: [PATCH 09/14] docs: Add more non-normative text for why the allFlags accessor exists Signed-off-by: Max VelDink --- specification/sections/02-providers.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index b69a87c4..5e0522f6 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -34,6 +34,9 @@ provider.getMetadata().getName(); // "my-custom-provider" provider.getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] ``` +This operation should not be confused with bulk evaluation of all flags. +This is an informative operation available to clients for understanding which flag keys are currently active from a provider. +Example usages include building a debug screen based on available flags and detecting stale flag evaluations. For some providers, fetching all flags is an expensive operation. If there is language support, consider implementing this as an asynchronous operation. ### 2.2 Flag Value Resolution From 6465990916c153b6a1ae2d318403cec52e7c9157 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Wed, 28 Feb 2024 06:00:13 -0500 Subject: [PATCH 10/14] docs: PR fixes Co-authored-by: Todd Baert Co-authored-by: Michael Beemer Signed-off-by: Max VelDink --- specification.json | 4 ++-- specification/sections/01-flag-evaluation.md | 2 +- specification/sections/02-providers.md | 4 ++-- specification/types.md | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/specification.json b/specification.json index cb69d2ec..da731265 100644 --- a/specification.json +++ b/specification.json @@ -87,7 +87,7 @@ { "id": "Requirement 1.2.3", "machine_id": "requirement_1_2_3", - "content": "The client interface MUST define a `allFlagMetadata` member or accessor, returning a collection of flag metadata from the provider.", + "content": "The client interface MUST define a `all flag metadata` member or accessor, returning a collection of flag metadata from the provider.", "RFC 2119 keyword": "MUST", "children": [] }, @@ -368,7 +368,7 @@ { "id": "Requirement 2.1.2", "machine_id": "requirement_2_1_2", - "content": "The provider MAY define an `allFlagMetadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider.", + "content": "The provider MAY define an `all flag metadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider.", "RFC 2119 keyword": "MAY", "children": [] }, diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index 3d229519..56dc36ea 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -173,7 +173,7 @@ For backwards compatibility, implementations should consider `name` an alias to #### Requirement 1.2.3 -> The client interface **MUST** define a `allFlagMetadata` member or accessor, returning a collection of flag metadata from the provider. +> The client interface **MUST** define a `all flag metadata` member or accessor, returning a collection of flag metadata from the provider. ```typescript client.getAllFlagMetadata() // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 5e0522f6..4508df5b 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -28,13 +28,13 @@ provider.getMetadata().getName(); // "my-custom-provider" #### Requirement 2.1.2 -> The provider **MAY** define an `allFlagMetadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider. +> The provider **MAY** define an `all flag metadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider. ```typescript provider.getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] ``` -This operation should not be confused with bulk evaluation of all flags. +This operation should not be confused with a bulk evaluation of all flags. This is an informative operation available to clients for understanding which flag keys are currently active from a provider. Example usages include building a debug screen based on available flags and detecting stale flag evaluations. For some providers, fetching all flags is an expensive operation. If there is language support, consider implementing this as an asynchronous operation. diff --git a/specification/types.md b/specification/types.md index 23619ed1..e8a41228 100644 --- a/specification/types.md +++ b/specification/types.md @@ -127,8 +127,8 @@ A structure containing the following fields: A structure which supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. -`key` is a required property with a value of `string`. -`type` is an optional property with a `string` value indicating which client resolution method should be used to resolve the flag key. +`key` is a required property with a value of type `string`. +`type` is an optional property with a value of type `string`, indicating which client resolution method should be used to resolve the flag key. This structure is populated by a provider for use by an [Application Author](./glossary.md#application-author) via the [Evaluation API](./glossary.md#evaluation-api) or an [Application Integrator](./glossary.md#application-integrator) via [hooks](./sections/04-hooks.md). @@ -137,7 +137,7 @@ This structure is populated by a provider for use by an [Application Author](./g A structure which carries information about the provider. In addition to the defined metadata fields below, arbitrary information can be stored here unique to the provider. -`name` is a required key with a string value. +`name` is a required key with a value of type string. ### Provider Status From f08ee9ea9c9e2213fc554bf2edf0a504c6ec5b14 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Fri, 1 Mar 2024 16:33:20 -0500 Subject: [PATCH 11/14] feat: return structure from getAllFlagMetadata calls Signed-off-by: Max VelDink --- specification.json | 4 ++-- specification/sections/01-flag-evaluation.md | 6 +++--- specification/sections/02-providers.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/specification.json b/specification.json index da731265..2323740a 100644 --- a/specification.json +++ b/specification.json @@ -87,7 +87,7 @@ { "id": "Requirement 1.2.3", "machine_id": "requirement_1_2_3", - "content": "The client interface MUST define a `all flag metadata` member or accessor, returning a collection of flag metadata from the provider.", + "content": "The client interface MUST define a `all flag metadata` member or accessor, containing a `flags` field or accessor which is a collection of flag metadata, from the provider.", "RFC 2119 keyword": "MUST", "children": [] }, @@ -368,7 +368,7 @@ { "id": "Requirement 2.1.2", "machine_id": "requirement_2_1_2", - "content": "The provider MAY define an `all flag metadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider.", + "content": "The provider MAY define an `all flag metadata` field or accessor, containing a `flags` field or accessor which is a collection of flag metadata, identifying all available flag keys in the provider.", "RFC 2119 keyword": "MAY", "children": [] }, diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index 56dc36ea..1cf9274f 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -173,10 +173,10 @@ For backwards compatibility, implementations should consider `name` an alias to #### Requirement 1.2.3 -> The client interface **MUST** define a `all flag metadata` member or accessor, returning a collection of flag metadata from the provider. +> The client interface **MUST** define a `all flag metadata` member or accessor, containing a `flags` field or accessor which is a collection of flag metadata, from the provider. ```typescript -client.getAllFlagMetadata() // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] +client.getAllFlagMetadata() // { flags: [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] } ``` This may return a language-idiomatic way of describing the absence of a value if the provider does not implement the `allFlagMetadata` member or accessor. @@ -516,4 +516,4 @@ see: [error codes](../types.md#error-code), [flag value resolution](./02-provide The SDK ensures that if the provider's lifecycle methods terminate with an `error code`, that error code is included in any associated error events and returned/thrown errors/exceptions. -see: [error codes](../types.md#error-code) \ No newline at end of file +see: [error codes](../types.md#error-code) diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 4508df5b..0c1f75eb 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -28,10 +28,10 @@ provider.getMetadata().getName(); // "my-custom-provider" #### Requirement 2.1.2 -> The provider **MAY** define an `all flag metadata` field or accessor of type collection of flag_metadata, which identifies all available flag keys in the provider. +> The provider **MAY** define an `all flag metadata` field or accessor, containing a `flags` field or accessor which is a collection of flag metadata, identifying all available flag keys in the provider. ```typescript -provider.getAllFlagMetadata(); // [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] +provider.getAllFlagMetadata(); // { flags: [{"key": "featureA", "type": "boolean"}, {"key": "featureB", "type": "string"}] } ``` This operation should not be confused with a bulk evaluation of all flags. From df54e357437b8a2b6629928f39ad7cf2892af6b5 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Thu, 7 Mar 2024 05:25:23 -0500 Subject: [PATCH 12/14] docs: Clarify Types changes Signed-off-by: Max VelDink --- specification/types.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specification/types.md b/specification/types.md index b6e7235a..5db3fcce 100644 --- a/specification/types.md +++ b/specification/types.md @@ -28,7 +28,7 @@ Structured data, presented however is idiomatic in the implementation language, ### Collection -A list or series of similar data types, presented however is idiomatic in the implementation language. +An unordered list or series of similar data types, presented however is idiomatic in the implementation language. ### Datetime @@ -126,6 +126,7 @@ A structure containing the following fields: ### Flag Metadata A structure which supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. +`key` and `type` are reserved properties. `key` is a required property with a value of type `string`. `type` is an optional property with a value of type `string`, indicating which client resolution method should be used to resolve the flag key. From b43feb0424d0119cf4944131e241f5c01ed43d8b Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Thu, 7 Mar 2024 05:38:14 -0500 Subject: [PATCH 13/14] docs: Add clarification on provider method around error or not implemented Signed-off-by: Max VelDink --- specification/sections/02-providers.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 0c1f75eb..58ac013e 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -38,6 +38,7 @@ This operation should not be confused with a bulk evaluation of all flags. This is an informative operation available to clients for understanding which flag keys are currently active from a provider. Example usages include building a debug screen based on available flags and detecting stale flag evaluations. For some providers, fetching all flags is an expensive operation. If there is language support, consider implementing this as an asynchronous operation. +If the provider does not implement this behavior or the flag metadata cannot currently be retrieved due to an error status, the language-idiomatic way of describing the absence of a value can be returned from this method. ### 2.2 Flag Value Resolution From dff60eac57dcf2d0238361bb88b11ad3ba264a37 Mon Sep 17 00:00:00 2001 From: Max VelDink Date: Thu, 7 Mar 2024 09:38:54 -0500 Subject: [PATCH 14/14] refactor: Clarify language around available flags Signed-off-by: Max VelDink --- specification/sections/02-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 58ac013e..01353fd9 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -35,7 +35,7 @@ provider.getAllFlagMetadata(); // { flags: [{"key": "featureA", "type": "boolean ``` This operation should not be confused with a bulk evaluation of all flags. -This is an informative operation available to clients for understanding which flag keys are currently active from a provider. +This is an informative operation available to clients for understanding which flag keys are currently available from a provider. Example usages include building a debug screen based on available flags and detecting stale flag evaluations. For some providers, fetching all flags is an expensive operation. If there is language support, consider implementing this as an asynchronous operation. If the provider does not implement this behavior or the flag metadata cannot currently be retrieved due to an error status, the language-idiomatic way of describing the absence of a value can be returned from this method.