You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## This PR
- updates the code default ADR to use `FLAG_NOT_FOUND` errors codes
instead of an undefined value.
### Notes
This update will have nearly identical end results but will be easier to
implement and more consistent. Core to this change is switching from
using an empty value as the indicator to using the `FLAG_NOT_FOUND`
error code. While this may seem odd at first, it's in line with the
behavior a user sees when first releasing a disabled flag. This will
allow users to `create a new disabled flag` -> `enable the flag for a
subset of users without impacting others` -> `enable the flag for
everyone` -> `deprecate the flag`.
---------
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
- Return HTTP 200 with response body that omits both value and variant fields
142
-
- Reason field set to "DEFAULT" to indicate delegation
143
-
- Clear distinction from error cases (which return 4xx/5xx)
144
-
145
-
**flagd RPC**:
146
-
- Omit both the type-specific value field and variant field in response messages
147
-
- Use protobuf field presence to signal "no opinion from server"
148
-
- No changes needed to RPC method signatures
149
-
150
-
5.**Provider Implementation**:
151
-
- Check for presence/absence of value field in responses
152
-
- When value is absent and reason is "DEFAULT", use code-defined default
153
-
- When value is present (even if null/false/empty), use that value
154
-
- Variant field will also be absent in delegation responses, resulting in undefined variant in resolution details
155
-
- Responses with value fields work as before, maintaining backward compatibility
85
+
3.**Provider Implementation**:
86
+
- No changes to existing providers
156
87
157
88
### Design Rationale
158
89
159
-
**Using "DEFAULT" reason**: We intentionally reuse the existing "DEFAULT" reason code rather than introducing a new one (like "CODE_DEFAULT"). The distinction between a configuration default and code default is clear from the response structure:
160
-
161
-
- Configuration default: Has both value and variant fields
162
-
- Code default: Omits both value and variant fields
163
-
164
-
**Field Omission Pattern**: Using field presence/absence is a well-established pattern in protocol design:
90
+
**Using "ERROR" reason**: We intentionally reuse the existing "ERROR" reason code rather than introducing a new one (like "CODE_DEFAULT"). This retains the current behavior of an disabled flag and allows for progressive enablement of a flag without unexpected variations in flag evaluation behavior.
165
91
166
-
- Unambiguous: Cannot confuse "null value" with "no opinion"
167
-
- Language agnostic: Works across type systems
168
-
- Protocol friendly: Natural in both JSON and Protobuf
169
-
- Backward compatible: Existing responses always include values
The omission of both value and variant fields creates a clear, consistent signal that the server is fully delegating the decision to the client's code default.
173
-
174
-
This approach maintains compatibility with the established OpenFeature terminology while providing clear semantics through response structure.
94
+
- The "ERROR" reason is already used for cases where the flag is not found or misconfigured, so it aligns with the intent of using code defaults.
95
+
- This approach avoids introducing new reason codes that would require additional handling in providers and clients.
175
96
176
97
### API changes
177
98
@@ -197,10 +118,14 @@ flags:
197
118
198
119
#### Single flag evaluation response
199
120
121
+
A single flag evaluation returns a `404` status code.
122
+
200
123
```json
201
124
{
202
125
"key": "my-feature",
203
-
"reason": "DEFAULT",
126
+
"errorCode": "FLAG_NOT_FOUND",
127
+
// Optional error details
128
+
"errorDetails": "Targeting not matched, using code default",
204
129
"metadata": {}
205
130
}
206
131
```
@@ -210,59 +135,21 @@ flags:
210
135
```json
211
136
{
212
137
"flags": [
213
-
{
214
-
"key": "my-feature",
215
-
"reason": "DEFAULT",
216
-
"metadata": {}
217
-
}
138
+
// Flag is omitted from bulk response
218
139
]
219
140
}
220
141
```
221
142
222
-
Note: Both `value` and `variant` fields are intentionally omitted to signal "use code default"
223
-
224
143
**flagd RPC Response** (ResolveBooleanResponse):
225
144
226
145
```protobuf
227
146
{
228
-
"reason": "DEFAULT",
147
+
"reason": "ERROR",
148
+
"errorCode": "FLAG_NOT_FOUND",
229
149
"metadata": {}
230
150
}
231
151
```
232
152
233
-
Both the type-specific value field and variant field are omitted
234
-
235
-
**Provider behavior**:
236
-
237
-
1. Check response for presence of value field
238
-
2. If value field is absent and error code is absent , use code-defined default
239
-
3. If value field is present (even if null/false/empty), use that value
240
-
4. The variant field will also be absent when delegating to code defaults
241
-
5. This logic is consistent across in-process, RPC, and OFREP modes
242
-
243
-
This approach clearly differentiates between:
244
-
245
-
- Server returning an actual value with a variant (both fields present)
246
-
- Server delegating to code default (both fields absent)
0 commit comments