Flag Manifest format for code generation of strongly-typed accessors #383
Replies: 4 comments 6 replies
-
I see this as a very interesting topic and was wondering if you've had any thoughts on how this could support "object type flags" and with that nesting? |
Beta Was this translation helpful? Give feedback.
-
In regards to being able to list the allowed values for a flag, I see that as a very powerful concept for the code generator use case. It would allow generators in many languages to enforce the specific values in the type system. For example in Typescript // MyFlag can only have values "value1", "value2", or "value3"
import { MyFlag } from './generated-flags.ts'
const flagValue = MyFlag(context)
// type error, flagValue cannot be 'value4'
if (flagValue === 'value4') {
} It would also allow future enforcement at the SDK level of "invalid" values delivered by the flagging backend. Ultimately the code should have control over the values it knows it can handle, and should be able to automatically reject invalid values that it gets served. |
Beta Was this translation helpful? Give feedback.
-
I like the proposal and it is simple enough to be implemented by most vendors. |
Beta Was this translation helpful? Give feedback.
-
Hey @anghelflorinm, I like the proposal! A proper CodeGen could improve the developer experience and allow users to tailor their experience. I experimented with something similar earlier this year, and the flag definition structure was nearly identical. This is what I had come up with: const FlagSchema = z.object({
key: z.string().describe('The key that will be used to uniquely identify the flag.'),
name: z.string().optional(),
description: z.string().optional(),
managementUrl: z.string().url().optional(),
returnType: z.enum(['boolean', 'string', 'float', 'double', 'object']),
defaultValue: z.any(),
}) I also had a similar structure for context attributes. The object looked like this: const ContextAttributeSchema = z.object({
key: z.string(),
name: z.string().optional(),
description: z.string().optional(),
managementUrl: z.string().url().optional(),
required: z.boolean().default(false),
type: z.enum(['boolean', 'string']),
}) The idea was to use the context attributes to make it easier for users to understand what context is actually being used. Basically, to summarize my thoughts, I love the idea! Perhaps if we could define some initial goals, we could collaborate on a prototype. |
Beta Was this translation helpful? Give feedback.
-
Hello! This is Florin, coming from Google. As we are looking to contribute on our end to OpenFeature, I am writing here to propose a manifest format for flags, initially just for the purpose of code generation.
Background
Specifying the flag meant for evaluation in OpenFeature is currently done via a string parameter:
Leaving the OpenFeature client directly visible to the users can lead to configuration problems in passing the wrong flag name or using the method returning a wrong type; also, flag name changes may result in unexpected behaviors.
Long-term, we would like to create some strongly-typed flag accessors that are automatically generated:
This would be done with a code generation tool, perhaps with a CLI or a bazel rule like so. The purpose of this proposal is not to discuss the details of the codegen, but rather propose a common format that could serve as a input to the codegen.
Proposal
I would like to propose a flag manifest format for specifying flags, that can be used as input to a potential code generation tool for strongly-typed flag accessors. The proposal is loosely inspired/simplified version of the flagd format and would follow such potential structure:
flags
: this will be a key containing inside it all flags, similar to flagdtype
: the type of the flag, specified via a string (e.g.string_flag
,bool_flag
,int_flag
)default_value
: its value must match the type specified in previous fielddocs
(string, optional): short explanation of the flag describing its purpose, to be used when generating codeBelow is an example of such configuration:
Challenges
While most fields are independent from one another, the one field that has some limitations and may potentially become redundant is the
type
field, as right now we can determine the type based on thedefault_value
. We could also discuss the best way of imposing restrictions upon the fields such as the characters allowed in the flag name (so it can be converted into a strong type) or having thetype
anddefault_value
consistent with each other.Advantages
Splitting flags into modules (Expansions for the future)
Currently, the format described above is meant for input in the codegen in the following way: 1 JSON structure results in one code module generation.
As flags grow (and should such format be adopted), a structure may potentially be needed to put all the flags together, but have them grouped by module inside a JSON file.
For this, all the modules can be placed inside a top level key called flag_modules, with each module name serving as a key to the flag manifest described above:
Alternatives Considered
It was considered incorporating into the flag logic more of the fields available in flagd, such as allowed values for the flag or targeting rules. However, as the logic of evaluation is executed on the backend side, it is better to have it separated, thus keeping the flag manifest with information as generic as possible.
It was also considered not adding the fields
flags
andflag_modules
(i.e. keeping the flag names as top level keys). However adding these fields allows for adding additional metadata to the manifest in future, depending on the use case.Future Work
In the long term, we may consider extending the manifest with additional fields. While logic/rules for flags are mostly separated from the flag manifest, adding a field for allowed values, similar to flagd, may be considered. Another field that may prove useful is adding
tags
; this would allow marking flags and applying additional rules for them such as exemptions and so on.Future work would also include integrating the Flag Manifest in the following way (below scenario is for external customers who would want to integrate this in their binary):
Customer (or flag management system) provides a conversion mechanism that takes as input their flag configuration and outputs this flag manifest format. We may implement such a converter for flagd.
The flag manifest is used as input to the flag management system so that the system understands what are the flags in a binary and what are their possible values.
The customer changes the flag values in their flag management system and by delivering a compatible flag configuration to binary they can change the binary behavior in a way that was designed by the binary developers.
Beta Was this translation helpful? Give feedback.
All reactions