Skip to content

Commit 66f2683

Browse files
thomaspoignantmarkphelpsbeeme1mrKavindu-Dodanrenovate[bot]
authored
feat: Client provider guidelines (#14)
* feat: Client provider spec Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update provider/specs/client.md Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * update with review comments Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Move to guideline folder Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Replace specification Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * add OpenAPI spec validator based on redocly cli (#15) Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * chore(deps): update actions/checkout action to v4 (#16) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update guideline/static-context-provider.md Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update guideline/static-context-provider.md Co-authored-by: Lukas Reining <lukas.reining@codecentric.de> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update guideline/static-context-provider.md Co-authored-by: Lukas Reining <lukas.reining@codecentric.de> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * update guidelines after removing configuration endpoint Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * adding change context Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: Allow any reason (#20) Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat!: change minPollingInterval field name to mention millisecond (#25) * feat!: change minPollingInterval field name to mention millisecond Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * change name to ms Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> --------- Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: Group API in core and extensions (#23) Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat!: Reverse the logic for supportedTypes (#24) * feat!: Reverse the logic for supportedTypes Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * fix Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> --------- Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * doc: adding providers link (#26) Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * make flags property mandatory for bulk evaluation success response (#27) Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: Typo in header name (#28) Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * add optional targeting key property (#30) Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * fix: use correct header name for 429 bulk response (#32) Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: Specify caching for OFREP in server providers (#17) Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> Signed-off-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com> Co-authored-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: add flag set metadata for bulk response and failures (#34) Signed-off-by: Todd Baert <todd.baert@dynatrace.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Fixups: Add operationIds, remove invalid property, fix tag casing (#35) Signed-off-by: Honza Dvorsky <honza@apple.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * ci: switch OpenAPI validators (#36) Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * fix: address style issues Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update static-context-provider.md Co-authored-by: Lukas Reining <lukas.reining@codecentric.de> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update static-context-provider.md Co-authored-by: Lukas Reining <lukas.reining@codecentric.de> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * adding timeout Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: Server provider guidelines (#42) * feat: Server provider guideline Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * adding timeout Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> --------- Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * feat: Group API in core and extensions (#23) Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update guideline/static-context-provider.md Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> * Update openapi.yaml Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> --------- Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org> Signed-off-by: Thomas Poignant <thomas.poignant@gmail.com> Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com> Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com> Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com> Signed-off-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com> Signed-off-by: Todd Baert <todd.baert@dynatrace.com> Signed-off-by: Honza Dvorsky <honza@apple.com> Co-authored-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com> Co-authored-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Lukas Reining <lukas.reining@codecentric.de> Co-authored-by: Michel TURPIN <michel.turpin1@gmail.com> Co-authored-by: Roman Dmytrenko <rdmytrenko@gmail.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com> Co-authored-by: Honza Dvorsky <honza@apple.com>
1 parent d151b98 commit 66f2683

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

guideline/static-context-provider.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Creating an OFREP client provider
2+
3+
OpenFeature Remote Evaluation Protocol (OFREP) is an API specification for feature flagging that allows the use of generic providers to connect to any feature flag management systems that supports the protocol.
4+
5+
In this document, we will specify how to write an OFREP provider using the [static-context-paradigm](https://openfeature.dev/specification/glossary/#static-context-paradigm) that is used on client side applications typically operating in the context of a single user.
6+
7+
**Pre-requisite:**
8+
- Understanding of [general provider concepts](https://openfeature.dev/docs/reference/concepts/provider/)
9+
- Understanding of the [OFREP](../../README.md)
10+
- Understanding of the [OFREP OpenAPI specification](../../service/openapi.yaml)
11+
12+
## Configuration
13+
An OFREP client provider implementation must, at the time of creation, accept at least these options
14+
- `baseURL`: The base URL of the [flag management system](https://openfeature.dev/specification/glossary#flag-management-system).
15+
This must be the base of the URL pointing before the `/ofrep` namespace of the API.
16+
- In the constructor, the provider should check if the `baseURL` is a valid URL and return an error if the URL is invalid.
17+
- `headers`: The headers to use when calling the OFREP endpoints *(e.g.:`Authorization`, Custom headers, etc ...)*.
18+
- `pollInterval`: The polling interval defining how often to update the cached flags in the provider.
19+
- If `pollInterval` is equal to 0, polling will be disabled.
20+
- See [polling section](#polling) for more details.
21+
- `timeoutMs`: This specifies the duration to wait for a response before canceling the HTTP request. If no value is provided, a default timeout of `10_000 milliseconds` must be applied.
22+
23+
## Initialize the provider
24+
The following describes the [initialization](https://openfeature.dev/specification/sections/providers#24-initialization) of an OFREP provider:
25+
26+
The `initialize()` function must follow those steps:
27+
1. Make a POST request to the `/ofrep/v1/evaluate/flags` endpoint with the evaluation context in the body.
28+
29+
**Request body example**:
30+
```json
31+
{
32+
"context": {
33+
"targetingKey": "f021d0f9-33b7-4b22-b0bd-9fec66ba1d7d",
34+
"firstname": "foo",
35+
"lastname": "bar",
36+
"email": "foo.bar@ofrep.dev"
37+
}
38+
}
39+
```
40+
41+
- If the endpoint returns an error, the `initialize()` function must error and exit.
42+
- If the request is successful:
43+
- The provider must store in a local cache all of the flags evaluation details returned by the API.
44+
- The provider must store the `ETag` header in the provider to be able to send it back later.
45+
2. If `pollInterval` is more than `0`, a polling mechanism must be started to periodically check for flag changes *([See polling section](#polling))*.
46+
47+
## Evaluation
48+
The evaluation MUST not perform any remote API calls and use the local cache.
49+
50+
When calling an evaluation function, the provider must follow those steps:
51+
1. Retrieve the evaluation details for this flag from the local cache.
52+
2. If the provider is not able to find the flag in the local cache, it must return an `FLAG_NOT_FOUND` error.
53+
3. If the evaluation details contains an error, the provider must map the error in provider to an OpenFeature error and return it.
54+
4. If the value of the evaluation details in the cache has a different type than the one expected by the evaluation function the provider must return a `TYPE_MISMATCH` error.
55+
5. If the evaluation details retrieved from the cache is successful, the provider returns the evaluation details.
56+
57+
58+
```mermaid
59+
flowchart TD
60+
A[evaluation function] --> D{Does the provider have an entry in cache for this flag key ?}
61+
D --> |NO| E(return a FLAG_NOT_FOUND error)
62+
D --> |YES| F{Is cached evaluation details in error?}
63+
F --> |YES| G(Map the error as an OpenFeature provider error and return it)
64+
F --> |NO| H{Are the flag and evaluation return types the same?}
65+
H --> |YES| I(return the evaluation response)
66+
H --> |NO| J(return a TYPE_MISMATCH error)
67+
```
68+
69+
## Polling
70+
The polling system must periodically (interval defined by `pollingInterval`) make a `POST` request to the `/ofrep/v1/evaluate/flags` endpoint with the evaluation context in the body to check if there is a change in the flags evaluation to be able to store it.
71+
If the flags changed, the provider cache for evaluation is updated.
72+
73+
When calling the API, if an `ETag` of a previous evaluation is available, it must be added to the [`If-None-Match`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/If-None-Match) header with the `ETag` as value.
74+
75+
When calling the API the provider can receive those response codes:
76+
- `304`: Means that the current cache is up-to-date.
77+
- `401`, `403`: The provider is not authorized to call the OFREP API. In that situation the provider should emit a `fatal` event and stop the polling mechanism. The provider will be in a [terminal error state](https://openfeature.dev/specification/sections/flag-evaluation#requirement-177).
78+
- `429`: The provider has reached the rate limit of the flag management system. In that situation the provider should read the `Retry-After` header from the response and ensure that no call to the endpoint happened before this date.
79+
- `200`: The cache is outdated. In that situation the provider must:
80+
1. Clear the actual cache.
81+
2. Cache the new evaluation details received.
82+
3. Read the `ETag` header and store it for future call the API.
83+
4. Emit an `ConfigurationChanged` event containing in the `flagsChanged` field, a list of the flag key that have changed.
84+
85+
## Change context
86+
In the client providers, a change of context should be handle to retrieve a new version of the cache, it is called that the [Provider context reconciliation](https://openfeature.dev/specification/sections/providers/#26-provider-context-reconciliation).
87+
88+
When the function `onContextChange` is called, the provider should call the `/ofrep/v1/evaluate/flags` endpoint with the evaluation context in the body to check if the cache needs to be updated. In that situation the provider must handle the response the same way it does for polling.

0 commit comments

Comments
 (0)