From e08b2a08ec811e6c8be496453e0302d7c165cb3a Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 18 Aug 2025 09:16:10 +0000 Subject: [PATCH 01/14] proposal: added draft propsal to add new flag-type field. Signed-off-by: Andrey --- docs/architecture-decisions/flag-type.md | 169 +++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 docs/architecture-decisions/flag-type.md diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md new file mode 100644 index 000000000..5c2a1367a --- /dev/null +++ b/docs/architecture-decisions/flag-type.md @@ -0,0 +1,169 @@ + + +--- +# Valid statuses: draft | proposed | rejected | accepted | superseded +status: draft +author: @andreyturkov +created: 2025-08-14 +updated: 2025-08-14 +--- + +# Extending Flag Definition with a Type Property + +## Background + +Currently, `flagd` exhibits inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. This inconsistent behavior is further detailed in bug report #1481. + +The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant`, which is not always a reliable source of truth for all possible variants. This can lead to unexpected errors and make it difficult for developers to debug their feature flags. + +To address this, we propose extending the flag definition with an optional `type` property. This would establish a clear and explicit type for each flag, ensuring that all variants conform to a single, authoritative type. This change aims to eliminate the current inconsistencies and provide a more robust and predictable type validation mechanism, ultimately improving the reliability and developer experience of `flagd`. + +## Requirements + +* The new `type` field in the flag definition must be optional to ensure backward compatibility. +* If the `type` field is present, `flagd` must validate that all variants of the flag conform to this type during initialization. +* Type mismatches found during initialization must be reported as errors. +* The `Resolve` and `ResolveAll` methods must use the `type` field for validation when it is available. +* The implementation must be consistent with the OpenFeature specification and the flag manifest schema. + +## Considered Options + +* **Consistent `defaultVariant` Validation:** Align the behavior of `Resolve` with `ResolveAll` by making `Resolve` validate the evaluated variant against the type of the `defaultVariant`. +* **API Extension with Explicit Flag Type:** Introduce an optional `type` property to the flag definition to serve as the authoritative source for type validation. + +## Proposal + +We propose to extend the flag definition with an optional `type` property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. + +By introducing an explicit `type` field, we establish a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. + +The new `type` field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `Object`, and no type validation will be performed against the `defaultVariant`. When the `type` field is present, `flagd` will enforce that all variants of the flag conform to the specified type. + +This change will make the behavior of `flagd` more predictable and reliable, improving the overall developer experience. It also aligns `flagd` with best practices for API design, where explicit type definitions are preferred over implicit ones. + + +### API changes + +The `flagd` flag definition will be updated to include an optional `type` property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"number"`, and `"object"`. + +#### JSON Schema + +The following changes will be made to the `schemas/json/flags.json` file: + +1. A new `type` property will be added to the `flag` definition: + +```json +"flag": { + "type": "object", + "properties": { + "type": { + "title": "Flag Type", + "description": "The type of the flag. If specified, all variants must conform to this type.", + "type": "string", + "enum": [ + "boolean", + "string", + "number", + "object" + ] + }, + "state": { + ... + }, + ... + } +} +``` + +2. The `booleanFlag`, `stringFlag`, `numberFlag`, and `objectFlag` definitions will be updated to enforce the `type` property: + +```json +"booleanFlag": { + "allOf": [ + { + "$ref": "#/definitions/flag" + }, + { + "$ref": "#/definitions/booleanVariants" + }, + { + "properties": { + "type": { + "const": "boolean" + } + } + } + ] +} +``` + +Similar changes will be made to `stringFlag`, `numberFlag`, and `objectFlag` to enforce their respective types. + +### Consequences + +* Good, because it improves the reliability and predictability of flag evaluations. +* Good, because it allows for early error detection of type mismatches. +* Good, because it improves the developer experience by making the API more explicit. +* Bad, because it adds a new field to the flag definition, which developers need to be aware of. +* Bad, because it requires updating all `flagd` SDKs to support the new field. + +### Timeline + +* **Phase 1: Core Implementation (2-4 weeks)** + * Update the `flagd` core to support the new `type` field. + * Implement the type validation logic. + * Update the JSON schema. + * Add unit and integration tests. +* **Phase 2: SDK Updates (4-8 weeks)** + * Update all official `flagd` SDKs to support the new `type` field. + * This will involve coordination with the maintainers of each SDK. +* **Phase 3: Documentation and Communication (1-2 weeks)** + * Update the `flagd` documentation to reflect the changes. + * Communicate the changes to the community through blog posts, and other channels. + + +### Open questions + +* How should `flagd` behave if the `type` field is specified but the `defaultVariant` has a different type? +* What is the exact mapping between the `type` field and the protobuf `oneof` value types? +* Should we add a new `type` field to the `AnyFlag` message in the protobuf definition? +* How will this change be communicated to the community and what is the migration path for users with existing flag configurations? + + +## More Information + +* **Bug Report:** [https://github.com/open-feature/flagd/issues/1481](https://github.com/open-feature/flagd/issues/1481) +* **OpenFeature Specification:** [https://openfeature.dev/docs/specification/](https://openfeature.dev/docs/specification/) +* **Flag Manifest Schema:** [https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json](https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json) \ No newline at end of file From 122620264cefd6f48e25a0465e1fd8fa18deca59 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 18 Aug 2025 15:08:20 +0000 Subject: [PATCH 02/14] proposal: text refinement and clean up Signed-off-by: Andrey --- docs/architecture-decisions/flag-type.md | 76 +++++++----------------- 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 5c2a1367a..2e4912d37 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -1,40 +1,6 @@ - - --- # Valid statuses: draft | proposed | rejected | accepted | superseded -status: draft +status: proposed author: @andreyturkov created: 2025-08-14 updated: 2025-08-14 @@ -42,13 +8,13 @@ updated: 2025-08-14 # Extending Flag Definition with a Type Property + ## Background -Currently, `flagd` exhibits inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. This inconsistent behavior is further detailed in bug report #1481. +Currently, `flagd` has inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. This inconsistent behavior is further detailed in bug report #1481. -The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant`, which is not always a reliable source of truth for all possible variants. This can lead to unexpected errors and make it difficult for developers to debug their feature flags. +The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`) , which is not always a reliable source of truth for all possible variants. This can lead to unexpected errors and make it difficult for developers to debug their feature flags. -To address this, we propose extending the flag definition with an optional `type` property. This would establish a clear and explicit type for each flag, ensuring that all variants conform to a single, authoritative type. This change aims to eliminate the current inconsistencies and provide a more robust and predictable type validation mechanism, ultimately improving the reliability and developer experience of `flagd`. ## Requirements @@ -58,26 +24,29 @@ To address this, we propose extending the flag definition with an optional `type * The `Resolve` and `ResolveAll` methods must use the `type` field for validation when it is available. * The implementation must be consistent with the OpenFeature specification and the flag manifest schema. + ## Considered Options * **Consistent `defaultVariant` Validation:** Align the behavior of `Resolve` with `ResolveAll` by making `Resolve` validate the evaluated variant against the type of the `defaultVariant`. * **API Extension with Explicit Flag Type:** Introduce an optional `type` property to the flag definition to serve as the authoritative source for type validation. + ## Proposal -We propose to extend the flag definition with an optional `type` property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. +This proposal is to extend the flag definition with an optional `type` property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. -By introducing an explicit `type` field, we establish a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. +By introducing an explicit `type` field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. The new `type` field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `Object`, and no type validation will be performed against the `defaultVariant`. When the `type` field is present, `flagd` will enforce that all variants of the flag conform to the specified type. -This change will make the behavior of `flagd` more predictable and reliable, improving the overall developer experience. It also aligns `flagd` with best practices for API design, where explicit type definitions are preferred over implicit ones. +This change will make the behavior of `flagd` more predictable and reliable. + - ### API changes The `flagd` flag definition will be updated to include an optional `type` property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"number"`, and `"object"`. + #### JSON Schema The following changes will be made to the `schemas/json/flags.json` file: @@ -133,11 +102,15 @@ Similar changes will be made to `stringFlag`, `numberFlag`, and `objectFlag` to ### Consequences -* Good, because it improves the reliability and predictability of flag evaluations. -* Good, because it allows for early error detection of type mismatches. -* Good, because it improves the developer experience by making the API more explicit. -* Bad, because it adds a new field to the flag definition, which developers need to be aware of. -* Bad, because it requires updating all `flagd` SDKs to support the new field. +#### The good +* It improves the reliability and predictability of flag evaluations. +* It allows for early error detection of type mismatches. +* It improves the developer experience by making the API more explicit. + +#### The bad +* It adds a new field to the flag definition, which developers need to be aware of. +* It requires updating all `flagd` SDKs to support the new field. +* It requires updating flag manifest schema ### Timeline @@ -153,17 +126,10 @@ Similar changes will be made to `stringFlag`, `numberFlag`, and `objectFlag` to * Update the `flagd` documentation to reflect the changes. * Communicate the changes to the community through blog posts, and other channels. - -### Open questions -* How should `flagd` behave if the `type` field is specified but the `defaultVariant` has a different type? -* What is the exact mapping between the `type` field and the protobuf `oneof` value types? -* Should we add a new `type` field to the `AnyFlag` message in the protobuf definition? -* How will this change be communicated to the community and what is the migration path for users with existing flag configurations? - ## More Information * **Bug Report:** [https://github.com/open-feature/flagd/issues/1481](https://github.com/open-feature/flagd/issues/1481) -* **OpenFeature Specification:** [https://openfeature.dev/docs/specification/](https://openfeature.dev/docs/specification/) +* **Flag schema** [https://flagd.dev/schema/v0/flags.json](https://flagd.dev/schema/v0/flags.json) * **Flag Manifest Schema:** [https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json](https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json) \ No newline at end of file From f1b01ef3704c557810f7c25f25b0bd8192231439 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 19 Aug 2025 09:56:02 +0000 Subject: [PATCH 03/14] chore: flag-type proposal updates Signed-off-by: Andrey --- docs/architecture-decisions/flag-type.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 2e4912d37..2290e53c0 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -37,7 +37,7 @@ This proposal is to extend the flag definition with an optional `type` property. By introducing an explicit `type` field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. -The new `type` field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `Object`, and no type validation will be performed against the `defaultVariant`. When the `type` field is present, `flagd` will enforce that all variants of the flag conform to the specified type. +The new `type` field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. When the `type` field is present, `flagd` will enforce that all variants of the flag conform to the specified type. This change will make the behavior of `flagd` more predictable and reliable. @@ -114,17 +114,16 @@ Similar changes will be made to `stringFlag`, `numberFlag`, and `objectFlag` to ### Timeline -* **Phase 1: Core Implementation (2-4 weeks)** - * Update the `flagd` core to support the new `type` field. - * Implement the type validation logic. - * Update the JSON schema. - * Add unit and integration tests. -* **Phase 2: SDK Updates (4-8 weeks)** - * Update all official `flagd` SDKs to support the new `type` field. - * This will involve coordination with the maintainers of each SDK. -* **Phase 3: Documentation and Communication (1-2 weeks)** - * Update the `flagd` documentation to reflect the changes. - * Communicate the changes to the community through blog posts, and other channels. +* **Phase 1: Core Implementation** + * Update the `flagd` core to support the new `type` field. + * Implement the type validation logic. + * Update the JSON schema. + * Add unit and integration tests. +* **Phase 2: SDK Updates** + * Update all `flagd` SDKs to support the new `type` field. + * Update flag manifest +* **Phase 3: Documentation** + * Update the `flagd` documentation to reflect the changes. From 8f4e0808d67f36deafaf8f701be588fea3b29a5b Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 19 Aug 2025 09:57:51 +0000 Subject: [PATCH 04/14] chore: flag-type proposal updates Signed-off-by: Andrey --- docs/architecture-decisions/flag-type.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 2290e53c0..74ba4cc6d 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -1,5 +1,4 @@ --- -# Valid statuses: draft | proposed | rejected | accepted | superseded status: proposed author: @andreyturkov created: 2025-08-14 From b8cfc68748b06298d8f5db9e9dab3b5af06b6e08 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 19 Aug 2025 16:14:11 +0000 Subject: [PATCH 05/14] chore: updated flag type ADR according to the remarks from PR Signed-off-by: Andrey --- docs/architecture-decisions/flag-type.md | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 74ba4cc6d..7b2152778 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -12,45 +12,44 @@ updated: 2025-08-14 Currently, `flagd` has inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. This inconsistent behavior is further detailed in bug report #1481. -The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`) , which is not always a reliable source of truth for all possible variants. This can lead to unexpected errors and make it difficult for developers to debug their feature flags. +The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`) , which is not always a reliable source of truth for all possible variants. This issue is compounded by the planned support for code-defined defaults (as detailed in the [Support Code Default ADR](./support-code-default.md)), which allows the `defaultVariant` to be `null`. This makes it impossible to infer the flag's type from the `defaultVariant`, increasing the risk of runtime errors. ## Requirements -* The new `type` field in the flag definition must be optional to ensure backward compatibility. -* If the `type` field is present, `flagd` must validate that all variants of the flag conform to this type during initialization. +* The new `flagdType`field in the flag definition must be optional to ensure backward compatibility. +* If the `flagdType`field is present, `flagd` must validate that all variant values of the flag conform to this type during initialization. * Type mismatches found during initialization must be reported as errors. -* The `Resolve` and `ResolveAll` methods must use the `type` field for validation when it is available. +* The `Resolve` and `ResolveAll` methods must use the `flagdType`field for validation when it is available. * The implementation must be consistent with the OpenFeature specification and the flag manifest schema. ## Considered Options * **Consistent `defaultVariant` Validation:** Align the behavior of `Resolve` with `ResolveAll` by making `Resolve` validate the evaluated variant against the type of the `defaultVariant`. -* **API Extension with Explicit Flag Type:** Introduce an optional `type` property to the flag definition to serve as the authoritative source for type validation. +* **API Extension with Explicit Flag Type:** Introduce an optional `flagdType`property to the flag definition to serve as the authoritative source for type validation. ## Proposal -This proposal is to extend the flag definition with an optional `type` property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. +This proposal is to extend the flag definition with an optional `flagdType`property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. -By introducing an explicit `type` field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. +By introducing an explicit `flagdType`field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. -The new `type` field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. When the `type` field is present, `flagd` will enforce that all variants of the flag conform to the specified type. +The new `flagdType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. When the `flagdType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. This change will make the behavior of `flagd` more predictable and reliable. ### API changes -The `flagd` flag definition will be updated to include an optional `type` property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"number"`, and `"object"`. - +The `flagd` flag definition will be updated to include an optional `flagdType`property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"integer"`, `"float"`, and `"object"`. This aligns with the OpenFeature CLI and the flag manifest schema. #### JSON Schema The following changes will be made to the `schemas/json/flags.json` file: -1. A new `type` property will be added to the `flag` definition: +1. A new `flagdType`property will be added to the `flag` definition: ```json "flag": { @@ -63,7 +62,8 @@ The following changes will be made to the `schemas/json/flags.json` file: "enum": [ "boolean", "string", - "number", + "integer", + "float", "object" ] }, @@ -75,7 +75,7 @@ The following changes will be made to the `schemas/json/flags.json` file: } ``` -2. The `booleanFlag`, `stringFlag`, `numberFlag`, and `objectFlag` definitions will be updated to enforce the `type` property: +2. The `booleanFlag`, `stringFlag`, `integerFlag`, `floatFlag`, and `objectFlag` definitions will be updated to enforce the `flagdType`property: ```json "booleanFlag": { @@ -97,7 +97,7 @@ The following changes will be made to the `schemas/json/flags.json` file: } ``` -Similar changes will be made to `stringFlag`, `numberFlag`, and `objectFlag` to enforce their respective types. +Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `objectFlag` to enforce their respective types. ### Consequences @@ -114,12 +114,12 @@ Similar changes will be made to `stringFlag`, `numberFlag`, and `objectFlag` to ### Timeline * **Phase 1: Core Implementation** - * Update the `flagd` core to support the new `type` field. + * Update the `flagd` core to support the new `flagdType`field. * Implement the type validation logic. * Update the JSON schema. * Add unit and integration tests. * **Phase 2: SDK Updates** - * Update all `flagd` SDKs to support the new `type` field. + * Update all `flagd` SDKs to support the new `flagdType`field. * Update flag manifest * **Phase 3: Documentation** * Update the `flagd` documentation to reflect the changes. From 6ef6fceccdbe74b7ac18242112ac2a97b005cbe7 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 20 Aug 2025 13:50:27 +0000 Subject: [PATCH 06/14] chore: updated flag type ADR according to the remarks from PR Signed-off-by: Andrey --- docs/architecture-decisions/flag-type.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 7b2152778..90a550b3b 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -12,7 +12,7 @@ updated: 2025-08-14 Currently, `flagd` has inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. This inconsistent behavior is further detailed in bug report #1481. -The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`) , which is not always a reliable source of truth for all possible variants. This issue is compounded by the planned support for code-defined defaults (as detailed in the [Support Code Default ADR](./support-code-default.md)), which allows the `defaultVariant` to be `null`. This makes it impossible to infer the flag's type from the `defaultVariant`, increasing the risk of runtime errors. +The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`) , which is not always a reliable source of truth for all possible variants. This problem is getting worse by the planned support for code-defined defaults (as detailed in the [Support Code Default ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/support-code-default.md)), which allows the `defaultVariant` to be `null`. This makes it impossible to resolve the flag's type from the `defaultVariant`, increasing the risk of runtime errors. ## Requirements @@ -27,7 +27,7 @@ The root cause of this issue is the absence of a dedicated, authoritative type d ## Considered Options * **Consistent `defaultVariant` Validation:** Align the behavior of `Resolve` with `ResolveAll` by making `Resolve` validate the evaluated variant against the type of the `defaultVariant`. -* **API Extension with Explicit Flag Type:** Introduce an optional `flagdType`property to the flag definition to serve as the authoritative source for type validation. +* **API Extension with Explicit Flag Type:** Introduce an optional `flagdType`property to the flag definition to serve as the single source for type validation. ## Proposal @@ -102,30 +102,27 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o ### Consequences #### The good -* It improves the reliability and predictability of flag evaluations. -* It allows for early error detection of type mismatches. -* It improves the developer experience by making the API more explicit. + * It improves the reliability and predictability of flag evaluations. + * It allows for early error detection of type mismatches. + * It improves the developer experience by making the API more explicit. #### The bad -* It adds a new field to the flag definition, which developers need to be aware of. -* It requires updating all `flagd` SDKs to support the new field. -* It requires updating flag manifest schema + * It adds a new field to the flag definition, which developers need to be aware of. + * It requires updating all `flagd` SDKs to support the new field. ### Timeline * **Phase 1: Core Implementation** + * Update the JSON schema. * Update the `flagd` core to support the new `flagdType`field. * Implement the type validation logic. - * Update the JSON schema. * Add unit and integration tests. * **Phase 2: SDK Updates** * Update all `flagd` SDKs to support the new `flagdType`field. - * Update flag manifest * **Phase 3: Documentation** * Update the `flagd` documentation to reflect the changes. - ## More Information * **Bug Report:** [https://github.com/open-feature/flagd/issues/1481](https://github.com/open-feature/flagd/issues/1481) From 4a5081c1d288b5498112667d9d8b39a10bc09207 Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Wed, 20 Aug 2025 17:13:58 +0000 Subject: [PATCH 07/14] Signed-off-by: Andrey Turkov chore: updated flag type ADR according to the remarks from PR - fixed naming --- docs/architecture-decisions/flag-type.md | 24 ++++++++++++------------ schemas | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 90a550b3b..ff7b442a7 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -17,39 +17,39 @@ The root cause of this issue is the absence of a dedicated, authoritative type d ## Requirements -* The new `flagdType`field in the flag definition must be optional to ensure backward compatibility. -* If the `flagdType`field is present, `flagd` must validate that all variant values of the flag conform to this type during initialization. +* The new `flagType`field in the flag definition must be optional to ensure backward compatibility. +* If the `flagType`field is present, `flagd` must validate that all variant values of the flag conform to this type during initialization. * Type mismatches found during initialization must be reported as errors. -* The `Resolve` and `ResolveAll` methods must use the `flagdType`field for validation when it is available. +* The `Resolve` and `ResolveAll` methods must use the `flagType`field for validation when it is available. * The implementation must be consistent with the OpenFeature specification and the flag manifest schema. ## Considered Options * **Consistent `defaultVariant` Validation:** Align the behavior of `Resolve` with `ResolveAll` by making `Resolve` validate the evaluated variant against the type of the `defaultVariant`. -* **API Extension with Explicit Flag Type:** Introduce an optional `flagdType`property to the flag definition to serve as the single source for type validation. +* **API Extension with Explicit Flag Type:** Introduce an optional `flagType`property to the flag definition to serve as the single source for type validation. ## Proposal -This proposal is to extend the flag definition with an optional `flagdType`property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. +This proposal is to extend the flag definition with an optional `flagType`property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. -By introducing an explicit `flagdType`field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. +By introducing an explicit `flagType`field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. -The new `flagdType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. When the `flagdType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. +The new `flagType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. When the `flagType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. This change will make the behavior of `flagd` more predictable and reliable. ### API changes -The `flagd` flag definition will be updated to include an optional `flagdType`property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"integer"`, `"float"`, and `"object"`. This aligns with the OpenFeature CLI and the flag manifest schema. +The `flagd` flag definition will be updated to include an optional `flagType`property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"integer"`, `"float"`, and `"object"`. This aligns with the OpenFeature CLI and the flag manifest schema. #### JSON Schema The following changes will be made to the `schemas/json/flags.json` file: -1. A new `flagdType`property will be added to the `flag` definition: +1. A new `flagType`property will be added to the `flag` definition: ```json "flag": { @@ -75,7 +75,7 @@ The following changes will be made to the `schemas/json/flags.json` file: } ``` -2. The `booleanFlag`, `stringFlag`, `integerFlag`, `floatFlag`, and `objectFlag` definitions will be updated to enforce the `flagdType`property: +2. The `booleanFlag`, `stringFlag`, `integerFlag`, `floatFlag`, and `objectFlag` definitions will be updated to enforce the `flagType`property: ```json "booleanFlag": { @@ -114,11 +114,11 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o * **Phase 1: Core Implementation** * Update the JSON schema. - * Update the `flagd` core to support the new `flagdType`field. + * Update the `flagd` core to support the new `flagType`field. * Implement the type validation logic. * Add unit and integration tests. * **Phase 2: SDK Updates** - * Update all `flagd` SDKs to support the new `flagdType`field. + * Update all `flagd` SDKs to support the new `flagType`field. * **Phase 3: Documentation** * Update the `flagd` documentation to reflect the changes. diff --git a/schemas b/schemas index 08b4c52d3..560e12d0c 160000 --- a/schemas +++ b/schemas @@ -1 +1 @@ -Subproject commit 08b4c52d3b86d686f11e74322dbfee775db91656 +Subproject commit 560e12d0c5722cb2ebec731bce2e2b4c78120c18 From 02131d1db1767084b1f96d4a36af198e5143e4bf Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Wed, 20 Aug 2025 17:16:05 +0000 Subject: [PATCH 08/14] Signed-off-by: Andrey Turkov fix: reverted schemas --- schemas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas b/schemas index 560e12d0c..08b4c52d3 160000 --- a/schemas +++ b/schemas @@ -1 +1 @@ -Subproject commit 560e12d0c5722cb2ebec731bce2e2b4c78120c18 +Subproject commit 08b4c52d3b86d686f11e74322dbfee775db91656 From 639519abdcba819da4de65be7f7b02f323194d40 Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Wed, 20 Aug 2025 17:18:40 +0000 Subject: [PATCH 09/14] Signed-off-by: Andrey Turkov fix: fixed schema naming for flag type --- docs/architecture-decisions/flag-type.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index ff7b442a7..9ec950354 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -55,7 +55,7 @@ The following changes will be made to the `schemas/json/flags.json` file: "flag": { "type": "object", "properties": { - "type": { + "flagType": { "title": "Flag Type", "description": "The type of the flag. If specified, all variants must conform to this type.", "type": "string", @@ -88,7 +88,7 @@ The following changes will be made to the `schemas/json/flags.json` file: }, { "properties": { - "type": { + "flagType": { "const": "boolean" } } From fdd6b67f741463dc0d6cd0ce2902bd50ab545abb Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Thu, 21 Aug 2025 09:56:16 +0000 Subject: [PATCH 10/14] Signed-off-by: Andrey Turkov fix: markdown check fix - added new line to the end of the file --- docs/architecture-decisions/flag-type.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 9ec950354..0b7176bad 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -127,4 +127,4 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o * **Bug Report:** [https://github.com/open-feature/flagd/issues/1481](https://github.com/open-feature/flagd/issues/1481) * **Flag schema** [https://flagd.dev/schema/v0/flags.json](https://flagd.dev/schema/v0/flags.json) -* **Flag Manifest Schema:** [https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json](https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json) \ No newline at end of file +* **Flag Manifest Schema:** [https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json](https://raw.githubusercontent.com/open-feature/cli/refs/heads/main/schema/v0/flag-manifest.json) From c132a8880fef7228c75e5bada65a5a174fe444cf Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Thu, 21 Aug 2025 13:54:46 +0000 Subject: [PATCH 11/14] Signed-off-by: Andrey Turkov fix: cleaned up flag type proposal by removing redundant sections --- docs/architecture-decisions/flag-type.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 0b7176bad..bc3617658 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -108,7 +108,6 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o #### The bad * It adds a new field to the flag definition, which developers need to be aware of. - * It requires updating all `flagd` SDKs to support the new field. ### Timeline @@ -117,9 +116,7 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o * Update the `flagd` core to support the new `flagType`field. * Implement the type validation logic. * Add unit and integration tests. -* **Phase 2: SDK Updates** - * Update all `flagd` SDKs to support the new `flagType`field. -* **Phase 3: Documentation** +* **Phase 2: Documentation** * Update the `flagd` documentation to reflect the changes. From effe9c76c6037015401900d40761cd127e4952cb Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Fri, 22 Aug 2025 08:32:55 +0000 Subject: [PATCH 12/14] Signed-off-by: Andrey Turkov fix: fixed markdown errors in flag-type.md --- docs/architecture-decisions/flag-type.md | 33 +++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index bc3617658..11bb30770 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -7,13 +7,17 @@ updated: 2025-08-14 # Extending Flag Definition with a Type Property - ## Background -Currently, `flagd` has inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. This inconsistent behavior is further detailed in bug report #1481. - -The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`) , which is not always a reliable source of truth for all possible variants. This problem is getting worse by the planned support for code-defined defaults (as detailed in the [Support Code Default ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/support-code-default.md)), which allows the `defaultVariant` to be `null`. This makes it impossible to resolve the flag's type from the `defaultVariant`, increasing the risk of runtime errors. +Currently, `flagd` has inconsistent behavior in type validation between its `Resolve` and `ResolveAll` API methods. +The `Resolve` method validates the evaluated flag variant against the type `T` requested by the client, while `ResolveAll` validates it against the type of the `defaultVariant` specified in the flag's definition. +This discrepancy can lead to situations where a flag evaluation succeeds with one method but fails with the other, depending on the evaluation context and the variant returned. +This inconsistent behavior is further detailed in bug report #1481. +The root cause of this issue is the absence of a dedicated, authoritative type definition for the flag itself. +Instead, the type is inferred from the `defaultVariant` or API itself (`T` from `Resolve`), which is not always a reliable source of truth for all possible variants. +This problem is getting worse by the planned support for code-defined defaults (as detailed in the [Support Code Default ADR](https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/support-code-default.md)), which allows the `defaultVariant` to be `null`. +This makes it impossible to resolve the flag's type from the `defaultVariant`, increasing the risk of runtime errors. ## Requirements @@ -23,24 +27,22 @@ The root cause of this issue is the absence of a dedicated, authoritative type d * The `Resolve` and `ResolveAll` methods must use the `flagType`field for validation when it is available. * The implementation must be consistent with the OpenFeature specification and the flag manifest schema. - ## Considered Options * **Consistent `defaultVariant` Validation:** Align the behavior of `Resolve` with `ResolveAll` by making `Resolve` validate the evaluated variant against the type of the `defaultVariant`. * **API Extension with Explicit Flag Type:** Introduce an optional `flagType`property to the flag definition to serve as the single source for type validation. - ## Proposal This proposal is to extend the flag definition with an optional `flagType`property. This approach is chosen over simply aligning the `Resolve` and `ResolveAll` validation because it addresses the root cause of the type inconsistency and provides a more robust, long-term solution. By introducing an explicit `flagType`field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. -The new `flagType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. When the `flagType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. +The new `flagType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. +When the `flagType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. This change will make the behavior of `flagd` more predictable and reliable. - ### API changes The `flagd` flag definition will be updated to include an optional `flagType`property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"integer"`, `"float"`, and `"object"`. This aligns with the OpenFeature CLI and the flag manifest schema. @@ -49,7 +51,7 @@ The `flagd` flag definition will be updated to include an optional `flagType`pro The following changes will be made to the `schemas/json/flags.json` file: -1. A new `flagType`property will be added to the `flag` definition: +1. A new `flagType`property will be added to the `flag` definition: ```json "flag": { @@ -75,7 +77,7 @@ The following changes will be made to the `schemas/json/flags.json` file: } ``` -2. The `booleanFlag`, `stringFlag`, `integerFlag`, `floatFlag`, and `objectFlag` definitions will be updated to enforce the `flagType`property: +1. The `booleanFlag`, `stringFlag`, `integerFlag`, `floatFlag`, and `objectFlag` definitions will be updated to enforce the `flagType`property: ```json "booleanFlag": { @@ -102,12 +104,14 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o ### Consequences #### The good - * It improves the reliability and predictability of flag evaluations. - * It allows for early error detection of type mismatches. - * It improves the developer experience by making the API more explicit. + +* It improves the reliability and predictability of flag evaluations. +* It allows for early error detection of type mismatches. +* It improves the developer experience by making the API more explicit. #### The bad - * It adds a new field to the flag definition, which developers need to be aware of. + +* It adds a new field to the flag definition, which developers need to be aware of. ### Timeline @@ -119,7 +123,6 @@ Similar changes will be made to `stringFlag`, `integerFlag`, `floatFlag`, and `o * **Phase 2: Documentation** * Update the `flagd` documentation to reflect the changes. - ## More Information * **Bug Report:** [https://github.com/open-feature/flagd/issues/1481](https://github.com/open-feature/flagd/issues/1481) From a0157ca935e96b4a28ddba0af6fbc5321dbc1308 Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Fri, 29 Aug 2025 08:16:07 +0000 Subject: [PATCH 13/14] Signed-off-by: Andrey Turkov fix: adressed review comments --- docs/architecture-decisions/flag-type.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 11bb30770..4a97ac97b 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -38,14 +38,28 @@ This proposal is to extend the flag definition with an optional `flagType`proper By introducing an explicit `flagType`field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. -The new `flagType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will treat the flag as having `object`, and no type validation will be performed against the `defaultVariant`. -When the `flagType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. +The new `flagdType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will fall back to infer the flag type from its variants. As the flag schema enforces that all variants are of the same type, the type of the first variant will be used. When the `flagdType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. This change will make the behavior of `flagd` more predictable and reliable. ### API changes -The `flagd` flag definition will be updated to include an optional `flagType`property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"integer"`, `"float"`, and `"object"`. This aligns with the OpenFeature CLI and the flag manifest schema. +The `flagd` flag definition will be updated to include an optional `flagType`property. This property will be a string enum with the following possible values: `"boolean"`, `"string"`, `"integer"`, `"float"`, and `"object"`. +This aligns with the OpenFeature CLI and the flag manifest schema. + +#### Handling of numeric types + +A known challenge with this approach is the differentiation between `integer` and `float` types, as JSON does not natively distinguish between them. However, maintaining this distinction is important for several reasons: + +* **Precision**: For certain use cases, such as when a flag's value represents a project number or other identifier, using floating-point numbers can lead to precision loss and unexpected behavior. Enforcing an integer type ensures that the value remains consistent and accurate. +* **Alignment with OpenFeature**: The OpenFeature specification includes both `integer` and `float` types. By supporting both, `flagd` remains consistent with the broader OpenFeature ecosystem, including the flag manifest used in the OpenFeature CLI. + +To address this, `flagd` will implement the following validation logic: + +* If `flagType` is set to `integer`, `flagd` will validate that all variants of the flag are whole numbers. +* If `flagType` is set to `float`, `flagd` will accept any numeric value. + +This validation will be performed during the initialization of the flag definition, allowing for early detection of type mismatches. #### JSON Schema From 144378e0319c1513e623fc187066e8bb647944e7 Mon Sep 17 00:00:00 2001 From: Andrey Turkov Date: Tue, 9 Sep 2025 10:01:51 +0000 Subject: [PATCH 14/14] Signed-off-by: Andrey Turkov fix: fixed typo in flag-type ADR --- docs/architecture-decisions/flag-type.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture-decisions/flag-type.md b/docs/architecture-decisions/flag-type.md index 4a97ac97b..a683b47b6 100644 --- a/docs/architecture-decisions/flag-type.md +++ b/docs/architecture-decisions/flag-type.md @@ -38,7 +38,7 @@ This proposal is to extend the flag definition with an optional `flagType`proper By introducing an explicit `flagType`field, it establishes a single source of truth for the flag's type, independent of its variants. This allows for early and consistent type validation during flag definition parsing, preventing type-related errors at runtime. -The new `flagdType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will fall back to infer the flag type from its variants. As the flag schema enforces that all variants are of the same type, the type of the first variant will be used. When the `flagdType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. +The new `flagType`field will be optional to maintain backward compatibility with existing flag configurations. If the field is omitted, `flagd` will fall back to infer the flag type from its variants. As the flag schema enforces that all variants are of the same type, the type of the first variant will be used. When the `flagType`field is present, `flagd` will enforce that all variants of the flag conform to the specified type. This change will make the behavior of `flagd` more predictable and reliable.