Skip to content

Commit c179236

Browse files
authored
chore: section clarity, harden API, providers (#149)
**Marking Evaluation API and Providers `hardening`** and a few non-functional changes here that improve structure. specifically: - explicitly mark and number all sections - section headings have consistent numbering (provider section numbering was different than the other docs) - removed "draft" language An alternative to marking all of `provider` and `evaluation API` as hardening would be just marking all existing sections therein as hardening, which might be better since we'd have to do that anyway if we added a new experimental section. see: #146 for more on release goals. Signed-off-by: Todd Baert <toddbaert@gmail.com>
1 parent 18d2f02 commit c179236

File tree

7 files changed

+70
-64
lines changed

7 files changed

+70
-64
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# OpenFeature Specification (Draft)
1+
# OpenFeature Specification
22

33
[![Roadmap](https://img.shields.io/static/v1?label=Roadmap&message=public&color=green)](https://github.com/orgs/open-feature/projects/1) [![Contributing](https://img.shields.io/static/v1?label=Contributing&message=guide&color=blue)](https://github.com/open-feature/.github/blob/main/CONTRIBUTING.md) [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/open-feature/.github/blob/main/CODE_OF_CONDUCT.md)
44

specification.json

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -185,101 +185,101 @@
185185
"children": []
186186
},
187187
{
188-
"id": "Requirement 2.1",
189-
"machine_id": "requirement_2_1",
188+
"id": "Requirement 2.1.1",
189+
"machine_id": "requirement_2_1_1",
190190
"content": "The provider interface MUST define a `metadata` member or accessor, containing a `name` field or accessor of type string, which identifies the provider implementation.",
191191
"RFC 2119 keyword": "MUST",
192192
"children": []
193193
},
194194
{
195-
"id": "Requirement 2.2",
196-
"machine_id": "requirement_2_2",
195+
"id": "Requirement 2.2.1",
196+
"machine_id": "requirement_2_2_1",
197197
"content": "The `feature provider` interface MUST define methods to resolve flag values, with parameters `flag key` (string, required), `default value` (boolean | number | string | structure, required) and `evaluation context` (optional), which returns a `flag resolution` structure.",
198198
"RFC 2119 keyword": "MUST",
199199
"children": []
200200
},
201201
{
202-
"id": "Condition 2.3",
203-
"machine_id": "condition_2_3",
202+
"id": "Condition 2.2.2",
203+
"machine_id": "condition_2_2_2",
204204
"content": "The implementing language type system differentiates between strings, numbers, booleans and structures.",
205205
"RFC 2119 keyword": null,
206206
"children": [
207207
{
208-
"id": "Conditional Requirement 2.3.1",
209-
"machine_id": "conditional_requirement_2_3_1",
208+
"id": "Conditional Requirement 2.2.2.1",
209+
"machine_id": "conditional_requirement_2_2_2_1",
210210
"content": "The `feature provider` interface MUST define methods for typed flag resolution, including boolean, numeric, string, and structure.",
211211
"RFC 2119 keyword": "MUST",
212212
"children": []
213213
}
214214
]
215215
},
216216
{
217-
"id": "Requirement 2.4",
218-
"machine_id": "requirement_2_4",
217+
"id": "Requirement 2.2.3",
218+
"machine_id": "requirement_2_2_3",
219219
"content": "In cases of normal execution, the `provider` MUST populate the `flag resolution` structure's `value` field with the resolved flag value.",
220220
"RFC 2119 keyword": "MUST",
221221
"children": []
222222
},
223223
{
224-
"id": "Requirement 2.5",
225-
"machine_id": "requirement_2_5",
224+
"id": "Requirement 2.2.4",
225+
"machine_id": "requirement_2_2_4",
226226
"content": "In cases of normal execution, the `provider` SHOULD populate the `flag resolution` structure's `variant` field with a string identifier corresponding to the returned flag value.",
227227
"RFC 2119 keyword": "SHOULD",
228228
"children": []
229229
},
230230
{
231-
"id": "Requirement 2.6",
232-
"machine_id": "requirement_2_6",
231+
"id": "Requirement 2.2.5",
232+
"machine_id": "requirement_2_2_5",
233233
"content": "The `provider` SHOULD populate the `flag resolution` structure's `reason` field with `\"DEFAULT\",` `\"TARGETING_MATCH\"`, `\"SPLIT\"`, `\"DISABLED\"`, `\"UNKNOWN\"`, `\"ERROR\"` or some other string indicating the semantic reason for the returned flag value.",
234234
"RFC 2119 keyword": "SHOULD",
235235
"children": []
236236
},
237237
{
238-
"id": "Requirement 2.7",
239-
"machine_id": "requirement_2_7",
238+
"id": "Requirement 2.2.6",
239+
"machine_id": "requirement_2_2_6",
240240
"content": "In cases of normal execution, the `provider` MUST NOT populate the `flag resolution` structure's `error code` field, or otherwise must populate it with a null or falsy value.",
241241
"RFC 2119 keyword": "MUST NOT",
242242
"children": []
243243
},
244244
{
245-
"id": "Requirement 2.8",
246-
"machine_id": "requirement_2_8",
245+
"id": "Requirement 2.2.7",
246+
"machine_id": "requirement_2_2_7",
247247
"content": "In cases of abnormal execution, the `provider` MUST indicate an error using the idioms of the implementation language, with an associated `error code` and optional associated `error message`.",
248248
"RFC 2119 keyword": "MUST",
249249
"children": []
250250
},
251251
{
252-
"id": "Condition 2.9",
253-
"machine_id": "condition_2_9",
252+
"id": "Condition 2.2.8",
253+
"machine_id": "condition_2_2_8",
254254
"content": "The implementation language supports generics (or an equivalent feature).",
255255
"RFC 2119 keyword": null,
256256
"children": [
257257
{
258-
"id": "Conditional Requirement 2.9.1",
259-
"machine_id": "conditional_requirement_2_9_1",
258+
"id": "Conditional Requirement 2.2.8.1",
259+
"machine_id": "conditional_requirement_2_2_8_1",
260260
"content": "The `flag resolution` structure SHOULD accept a generic argument (or use an equivalent language feature) which indicates the type of the wrapped `value` field.",
261261
"RFC 2119 keyword": "SHOULD",
262262
"children": []
263263
}
264264
]
265265
},
266266
{
267-
"id": "Requirement 2.10",
268-
"machine_id": "requirement_2_10",
267+
"id": "Requirement 2.3.1",
268+
"machine_id": "requirement_2_3_1",
269269
"content": "The provider interface MUST define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the evaluation life-cycle.",
270270
"RFC 2119 keyword": "MUST",
271271
"children": []
272272
},
273273
{
274-
"id": "Requirement 2.11",
275-
"machine_id": "requirement_2_11",
274+
"id": "Requirement 2.3.2",
275+
"machine_id": "requirement_2_3_2",
276276
"content": "In cases of normal execution, the `provider` MUST NOT populate the `flag resolution` structure's `error message` field, or otherwise must populate it with a null or falsy value.",
277277
"RFC 2119 keyword": "MUST NOT",
278278
"children": []
279279
},
280280
{
281-
"id": "Requirement 2.12",
282-
"machine_id": "requirement_2_12",
281+
"id": "Requirement 2.3.3",
282+
"machine_id": "requirement_2_3_3",
283283
"content": "In cases of abnormal execution, the `evaluation details` structure's `error message` field MAY contain a string containing additional detail about the nature of the error.",
284284
"RFC 2119 keyword": "MAY",
285285
"children": []

specification/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Possible statuses are described below:
4444

4545
### Experimental
4646

47-
[![Status](https://img.shields.io/static/v1?label=Status&message=experimental&color=orange)](https://github.com/open-feature/spec/tree/main/specification#experimental)
47+
[![experimental](https://img.shields.io/static/v1?label=Status&message=experimental&color=orange)](https://github.com/open-feature/spec/tree/main/specification#experimental)
4848

4949
Specification sections that are marked as `Experimental` contain functionality under active development. Breaking changes are allowed and may be made without deprecation notices or warnings with minor version updates. We recommend you use these features in experimental environments and not in production.
5050

@@ -54,7 +54,7 @@ Put simply:
5454
5555
### Hardening
5656

57-
[![Status](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening)
57+
[![hardening](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening)
5858

5959
Sections marked as `Hardening` describe functionality with an emphasis on stabilizing existing requirements. Breaking changes require consensus by the [Technical Steering Committee](https://github.com/open-feature/community/blob/main/governance-charter.md#tsc-members) but may still be made with minor version updates. These features are suitable for use in production environments. Feedback is encouraged.
6060

@@ -64,7 +64,7 @@ Put simply:
6464
6565
### Stable
6666

67-
[![Status](https://img.shields.io/static/v1?label=Status&message=stable&color=green)](https://github.com/open-feature/spec/tree/main/specification#stable)
67+
[![stable](https://img.shields.io/static/v1?label=Status&message=stable&color=green)](https://github.com/open-feature/spec/tree/main/specification#stable)
6868

6969
Sections marked as `Stable` do not allow breaking changes without a major version update. They can be used in production with a high degree of confidence.
7070

specification/sections/01-flag-evaluation.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ description: The specification that defines the developer facing feature flag ev
44
toc_max_heading_level: 4
55
---
66

7-
# Flag Evaluation API
7+
# 1. Flag Evaluation API
88

9-
**Status**: [Experimental](../README.md#document-statuses)
9+
[![hardening](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening)
1010

1111
## Overview
1212

1313
The `evaluation API` allows for the evaluation of feature flag values, independent of any flag control plane or vendor. In the absence of a [provider](./02-providers.md) the `evaluation API` uses the "No-op provider", which simply returns the supplied default flag value.
1414

15-
### API Initialization and Configuration
15+
### 1.1. API Initialization and Configuration
1616

1717
#### Requirement 1.1.1
1818

@@ -74,7 +74,7 @@ The name is a logical identifier for the client.
7474
7575
Clients may be created in critical code paths, and even per-request in server-side HTTP contexts. Therefore, in keeping with the principle that OpenFeature should never cause abnormal execution of the first party application, this function should never throw. Abnormal execution in initialization should instead occur during provider registration.
7676

77-
### Client Usage
77+
### 1.2. Client Usage
7878

7979
#### Requirement 1.2.1
8080

@@ -95,7 +95,9 @@ See [hooks](./04-hooks.md) for details.
9595
client.getMetadata().getName(); // "my-client"
9696
```
9797

98-
#### Flag Evaluation
98+
#### 1.3. Flag Evaluation
99+
100+
[![hardening](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening)
99101

100102
##### Requirement 1.3.1
101103

@@ -138,7 +140,9 @@ See [types](../types.md) for details.
138140

139141
> The `client` **SHOULD** guarantee the returned value of any typed flag evaluation method is of the expected type. If the value returned by the underlying provider implementation does not match the expected type, it's to be considered abnormal execution, and the supplied `default value` should be returned.
140142
141-
#### Detailed Flag Evaluation
143+
#### 1.4. Detailed Flag Evaluation
144+
145+
[![hardening](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening)
142146

143147
##### Requirement 1.4.1
144148

specification/sections/02-providers.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ description: The specification that defines the responsibilities and behaviors o
44
toc_max_heading_level: 4
55
---
66

7-
# Provider
7+
# 2. Provider
8+
9+
[![hardening](https://img.shields.io/static/v1?label=Status&message=hardening&color=yellow)](https://github.com/open-feature/spec/tree/main/specification#hardening)
810

911
## Overview
1012

@@ -14,21 +16,21 @@ Providers are the "translator" between the flag evaluation calls made in applica
1416

1517
![Provider](../assets/images/provider.png)
1618

17-
### Feature Provider Interface
19+
### 2.1. Feature Provider Interface
1820

19-
#### Requirement 2.1
21+
#### Requirement 2.1.1
2022

2123
> The provider interface **MUST** define a `metadata` member or accessor, containing a `name` field or accessor of type string, which identifies the provider implementation.
2224
2325
```typescript
2426
provider.getMetadata().getName(); // "my-custom-provider"
2527
```
2628

27-
#### Flag Value Resolution
29+
### 2.2 Flag Value Resolution
2830

2931
`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.
3032

31-
##### Requirement 2.2
33+
##### Requirement 2.2.1
3234

3335
> The `feature provider` interface **MUST** define methods to resolve flag values, with parameters `flag key` (string, required), `default value` (boolean | number | string | structure, required) and `evaluation context` (optional), which returns a `flag resolution` structure.
3436
@@ -39,11 +41,11 @@ resolveBooleanValue(flagKey, defaultValue, context);
3941

4042
see: [flag resolution structure](../types.md#flag-resolution), [flag value resolution](../glossary.md#flag-value-resolution)
4143

42-
##### Condition 2.3
44+
##### Condition 2.2.2
4345

4446
> The implementing language type system differentiates between strings, numbers, booleans and structures.
4547
46-
###### Conditional Requirement 2.3.1
48+
###### Conditional Requirement 2.2.2.1
4749

4850
> The `feature provider` interface **MUST** define methods for typed flag resolution, including boolean, numeric, string, and structure.
4951
@@ -61,29 +63,29 @@ ResolutionDetails resolveNumberValue(string flagKey, number defaultValue, contex
6163
ResolutionDetails resolveStructureValue(string flagKey, JsonObject defaultValue, context: EvaluationContext);
6264
```
6365

64-
##### Requirement 2.4
66+
##### Requirement 2.2.3
6567

6668
> In cases of normal execution, the `provider` **MUST** populate the `flag resolution` structure's `value` field with the resolved flag value.
6769
68-
##### Requirement 2.5
70+
##### Requirement 2.2.4
6971

7072
> In cases of normal execution, the `provider` **SHOULD** populate the `flag resolution` structure's `variant` field with a string identifier corresponding to the returned flag value.
7173
7274
For example, the flag value might be `3.14159265359`, and the variant field's value might be `"pi"`.
7375

7476
The value of the variant field might only be meaningful in the context of the flag management system associated with the provider. For example, the variant may be a UUID corresponding to the variant in the flag management system, or an index corresponding to the variant in the flag management system.
7577

76-
##### Requirement 2.6
78+
##### Requirement 2.2.5
7779

7880
> The `provider` **SHOULD** populate the `flag resolution` structure's `reason` field with `"DEFAULT",` `"TARGETING_MATCH"`, `"SPLIT"`, `"DISABLED"`, `"UNKNOWN"`, `"ERROR"` or some other string indicating the semantic reason for the returned flag value.
7981
8082
As indicated in the definition of the [`flag resolution`](../types.md#resolution-details) structure, the `reason` should be a string. This allows providers to reflect accurately why a flag was resolved to a particular value.
8183

82-
##### Requirement 2.7
84+
##### Requirement 2.2.6
8385

8486
> In cases of normal execution, the `provider` **MUST NOT** populate the `flag resolution` structure's `error code` field, or otherwise must populate it with a null or falsy value.
8587
86-
##### Requirement 2.8
88+
##### Requirement 2.2.7
8789

8890
> In cases of abnormal execution, the `provider` **MUST** indicate an error using the idioms of the implementation language, with an associated `error code` and optional associated `error message`.
8991
@@ -96,11 +98,11 @@ See [error code](../types.md#error-code) for details.
9698
throw new ProviderError(ErrorCode.INVALID_CONTEXT, "The 'foo' attribute must be a string.");
9799
```
98100

99-
##### Condition 2.9
101+
##### Condition 2.2.8
100102

101103
> The implementation language supports generics (or an equivalent feature).
102104
103-
###### Conditional Requirement 2.9.1
105+
###### Conditional Requirement 2.2.8.1
104106

105107
> The `flag resolution` structure **SHOULD** accept a generic argument (or use an equivalent language feature) which indicates the type of the wrapped `value` field.
106108
@@ -118,11 +120,11 @@ ResolutionDetails<number> resolveNumberValue(string flagKey, number defaultValue
118120
ResolutionDetails<MyStruct> resolveStructureValue(string flagKey, MyStruct defaultValue, context: EvaluationContext);
119121
```
120122

121-
#### Provider hooks
123+
#### 2.3. Provider hooks
122124

123125
A `provider hook` exposes a mechanism for `provider authors` to register [`hooks`](./04-hooks.md) to tap into various stages of the flag evaluation lifecycle. These hooks can be used to perform side effects and mutate the context for purposes of the provider. Provider hooks are not configured or controlled by the `application author`.
124126

125-
##### Requirement 2.10
127+
##### Requirement 2.3.1
126128

127129
> The provider interface **MUST** define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the evaluation life-cycle.
128130
@@ -141,10 +143,10 @@ class MyProvider implements Provider {
141143
}
142144
```
143145

144-
#### Requirement 2.11
146+
#### Requirement 2.3.2
145147

146148
> In cases of normal execution, the `provider` **MUST NOT** populate the `flag resolution` structure's `error message` field, or otherwise must populate it with a null or falsy value.
147149
148-
#### Requirement 2.12
150+
#### Requirement 2.3.3
149151

150152
> In cases of abnormal execution, the `evaluation details` structure's `error message` field **MAY** contain a string containing additional detail about the nature of the error.

specification/sections/03-evaluation-context.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: The specification that defines the structure and expectations of ev
44
toc_max_heading_level: 4
55
---
66

7-
# Evaluation Context
7+
# 3. Evaluation Context
88

99
**Status**: [Experimental](../README.md#document-statuses)
1010

@@ -14,7 +14,7 @@ The `evaluation context` provides ambient information for the purposes of flag e
1414

1515
The context might contain information about the end-user, the application, the host, or any other ambient data that might be useful in flag evaluation. For example, a flag system might define rules that return a specific value based on the user's email address, locale, or the time of day. The context provides this information. The context can be optionally provided at evaluation, and mutated in [before hooks](./04-hooks.md).
1616

17-
### Fields
17+
### 3.1 Fields
1818

1919
NOTE: Field casing is not specified, and should be chosen in accordance with language idioms.
2020

@@ -42,7 +42,7 @@ see: [structure](../types.md#structure), [datetime](../types.md#datetime)
4242
4343
The key uniquely identifies a field in the `evaluation context` and it should be unique across all types to avoid any collision when marshalling the `evaluation context` by the provider.
4444

45-
### Merging Context
45+
### 3.2 Merging Context
4646

4747
#### Requirement 3.2.1
4848

0 commit comments

Comments
 (0)