diff --git a/docs/reference/sdks/client/dart.mdx b/docs/reference/sdks/client/dart.mdx index fe5a4efdf..4d2346792 100644 --- a/docs/reference/sdks/client/dart.mdx +++ b/docs/reference/sdks/client/dart.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from dart-sdk. Edits should be made here: https://github.com/open-feature/dart-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:08 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:30 GMT+0000 (Coordinated Universal Time) --> # OpenFeature Dart Client SDK diff --git a/docs/reference/sdks/client/kotlin.mdx b/docs/reference/sdks/client/kotlin.mdx index e1eaddc50..372cc65a3 100644 --- a/docs/reference/sdks/client/kotlin.mdx +++ b/docs/reference/sdks/client/kotlin.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from kotlin-sdk. Edits should be made here: https://github.com/open-feature/kotlin-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/client/swift.mdx b/docs/reference/sdks/client/swift.mdx index bc2e7f7ce..dea9ac1d4 100644 --- a/docs/reference/sdks/client/swift.mdx +++ b/docs/reference/sdks/client/swift.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from swift-sdk. Edits should be made here: https://github.com/open-feature/swift-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; @@ -122,7 +122,7 @@ The SDK is an abstraction layer, it holds the evaluation context and tracking ev | ✅ | [MultiProvider](#multiprovider) | Combine multiple providers with configurable evaluation strategies. | | ✅ | [InMemoryProvider](#inmemoryprovider) | Resolve flags from an in-memory configuration, for demos and testing. | | ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| ❌ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | | ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ @@ -445,7 +445,15 @@ let cancellable = OpenFeatureAPI.shared.observe().sink { event in ### Shutdown -A shutdown function is not yet available in the iOS SDK. +`OpenFeatureAPI.shared.shutdown()` calls the active provider's `shutdown` and resets the API — provider, hooks and evaluation context — so it can be configured again later; the logger is kept. +Use `shutdownAndWait()` when you need to know the provider has finished, for example to flush tracking data before the process exits: + +```swift +await OpenFeatureAPI.shared.shutdownAndWait() +``` + +Providers are also shut down whenever they stop being used: `setProvider` shuts down the provider it replaces, and `clearProvider` shuts down the one it removes (`clearProviderAndWait` returns once that is done). +A provider that holds resources implements `shutdown() -> Future` to release them and revert to `.notReady` — `ProviderStatusTracker.reset()` does the latter — and resolves the `Future` when it is done; providers with nothing to release inherit a no-op default. ## Extending diff --git a/docs/reference/sdks/client/web/angular.mdx b/docs/reference/sdks/client/web/angular.mdx index f91f836f1..6265d6dd9 100644 --- a/docs/reference/sdks/client/web/angular.mdx +++ b/docs/reference/sdks/client/web/angular.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:30 GMT+0000 (Coordinated Universal Time) -->

diff --git a/docs/reference/sdks/client/web/index.mdx b/docs/reference/sdks/client/web/index.mdx index 8a70a6324..08db68633 100644 --- a/docs/reference/sdks/client/web/index.mdx +++ b/docs/reference/sdks/client/web/index.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/client/web/react.mdx b/docs/reference/sdks/client/web/react.mdx index d19b5a309..bdc0cc729 100644 --- a/docs/reference/sdks/client/web/react.mdx +++ b/docs/reference/sdks/client/web/react.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/cpp.mdx b/docs/reference/sdks/server/cpp.mdx index c82683039..c10e52605 100644 --- a/docs/reference/sdks/server/cpp.mdx +++ b/docs/reference/sdks/server/cpp.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from cpp-sdk. Edits should be made here: https://github.com/open-feature/cpp-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:08 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:30 GMT+0000 (Coordinated Universal Time) -->

diff --git a/docs/reference/sdks/server/dart.mdx b/docs/reference/sdks/server/dart.mdx index bbe1c9322..f4f4f1f66 100644 --- a/docs/reference/sdks/server/dart.mdx +++ b/docs/reference/sdks/server/dart.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from dart-sdk. Edits should be made here: https://github.com/open-feature/dart-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:30 GMT+0000 (Coordinated Universal Time) --> **Release status:** The server SDK has regular, non-beta releases on diff --git a/docs/reference/sdks/server/dotnet.mdx b/docs/reference/sdks/server/dotnet.mdx index 3ee6f31d6..5d89f8fd3 100644 --- a/docs/reference/sdks/server/dotnet.mdx +++ b/docs/reference/sdks/server/dotnet.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from dotnet-sdk. Edits should be made here: https://github.com/open-feature/dotnet-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/go.mdx b/docs/reference/sdks/server/go.mdx index 9c0d0483b..de57a5300 100644 --- a/docs/reference/sdks/server/go.mdx +++ b/docs/reference/sdks/server/go.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from go-sdk. Edits should be made here: https://github.com/open-feature/go-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; @@ -20,8 +20,8 @@ import MCPInstall from '@site/src/partials/mcp-install'; Specification - - Release + + Release
diff --git a/docs/reference/sdks/server/java.mdx b/docs/reference/sdks/server/java.mdx index 5ac10d360..390811a26 100644 --- a/docs/reference/sdks/server/java.mdx +++ b/docs/reference/sdks/server/java.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from java-sdk. Edits should be made here: https://github.com/open-feature/java-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:28 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/javascript/index.mdx b/docs/reference/sdks/server/javascript/index.mdx index cbb8dc40a..35c307028 100644 --- a/docs/reference/sdks/server/javascript/index.mdx +++ b/docs/reference/sdks/server/javascript/index.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:28 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/javascript/nestjs.mdx b/docs/reference/sdks/server/javascript/nestjs.mdx index 2adc856a5..023c08300 100644 --- a/docs/reference/sdks/server/javascript/nestjs.mdx +++ b/docs/reference/sdks/server/javascript/nestjs.mdx @@ -11,7 +11,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:28 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/php.mdx b/docs/reference/sdks/server/php.mdx index 653e0c8a0..c79d23db8 100644 --- a/docs/reference/sdks/server/php.mdx +++ b/docs/reference/sdks/server/php.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from php-sdk. Edits should be made here: https://github.com/open-feature/php-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/python.mdx b/docs/reference/sdks/server/python.mdx index f4b2139d3..6c2216b51 100644 --- a/docs/reference/sdks/server/python.mdx +++ b/docs/reference/sdks/server/python.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from python-sdk. Edits should be made here: https://github.com/open-feature/python-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:06 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:29 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install'; diff --git a/docs/reference/sdks/server/ruby.mdx b/docs/reference/sdks/server/ruby.mdx index 3b1974c69..8d2dfa69d 100644 --- a/docs/reference/sdks/server/ruby.mdx +++ b/docs/reference/sdks/server/ruby.mdx @@ -11,19 +11,19 @@ This content has been automatically generated from ruby-sdk. Edits should be made here: https://github.com/open-feature/ruby-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:07 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:30 GMT+0000 (Coordinated Universal Time) --> import MCPInstall from '@site/src/partials/mcp-install';

- - Specification + + Specification - - Release + + Release @@ -82,7 +82,13 @@ OpenFeature::SDK.configure do |config| config.set_provider(OpenFeature::SDK::Provider::InMemoryProvider.new( { "flag1" => true, - "flag2" => 1 + "flag2" => 1, + # Variant flags report a variant and reason, and can target on the evaluation context + "flag3" => OpenFeature::SDK::Provider::InMemoryProvider::Flag.new( + variants: {"on" => true, "off" => false}, + default_variant: "off", + context_evaluator: ->(ctx) { "on" if ctx&.targeting_key == "beta-user" } + ) } )) end @@ -161,9 +167,6 @@ rescue OpenFeature::SDK::ProviderInitializationError => e puts "Original error: #{e.original_error}" end -# With custom timeout (default is 30 seconds) -OpenFeature::SDK.set_provider_and_wait(my_provider, timeout: 60) - # Domain-specific provider OpenFeature::SDK.set_provider_and_wait(my_provider, domain: "feature-flags") @@ -288,6 +291,7 @@ Log output uses a structured key=value format: Clients can be assigned to a domain. A domain is a logical identifier which can be used to associate clients with a particular provider. If a domain has no associated provider, the default provider is used. +Clients look up their domain's provider on every call, so a client created before `set_provider` follows the new binding. ```ruby OpenFeature::SDK.configure do |config| @@ -301,28 +305,35 @@ legacy_flag_client = OpenFeature::SDK.build_client(domain: "legacy_flags") ### Eventing Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. -Initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider. -Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`. +Providers emit initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) from `init`. +A provider without `init` is `READY` as soon as it's registered, and its `PROVIDER_READY` handlers run before `set_provider` returns. +For providers that define `init` but not `emits_lifecycle_events?` returning `true`, the SDK emits `PROVIDER_READY` after `init` returns and `PROVIDER_ERROR` if it raises. +That path is deprecated (spec Appendix E), and the SDK logs a deprecation warning once per provider class to its configured logger. +Handlers for events a provider emits from `init` run while `init` is still in progress, so they can't call `set_provider_and_wait` for that same provider. +Some providers emit additional events: `PROVIDER_CONFIGURATION_CHANGED`, `PROVIDER_STALE`, `PROVIDER_RECONCILING` and `PROVIDER_CONTEXT_CHANGED`. +Handlers receive a hash with the `provider_name` and any details the provider sent, such as `message` or `error_code`. Please refer to the documentation of the provider you're using to see what events are supported. ```ruby # Register event handlers at the API (global) level ready_handler = ->(event_details) do - puts "Provider #{event_details[:provider].metadata.name} is ready!" + puts "Provider #{event_details[:provider_name]} is ready!" end OpenFeature::SDK.add_handler(OpenFeature::SDK::ProviderEvent::PROVIDER_READY, ready_handler) -# The SDK automatically emits lifecycle events. Providers can emit additional spontaneous events -# using the EventEmitter mixin to signal internal state changes like configuration updates. +# Providers emit events using the EventEmitter mixin: lifecycle events from init, and spontaneous +# events to signal internal state changes like configuration updates. class MyEventAwareProvider include OpenFeature::SDK::Provider::EventEmitter + def emits_lifecycle_events? = true + def init(evaluation_context) # Start background process to monitor for configuration changes - # Note: SDK automatically emits PROVIDER_READY when init completes successfully start_background_process + emit_event(OpenFeature::SDK::ProviderEvent::PROVIDER_READY) end def start_background_process @@ -352,6 +363,9 @@ This should only be called when your application is in the process of shutting d OpenFeature::SDK.shutdown ``` +The SDK also shuts down a replaced provider once no domain uses it. +Events from shut-down providers are ignored. + Individual providers can implement a `shutdown` method to perform cleanup: ```ruby @@ -433,6 +447,29 @@ class MyRequestScopedPropagator end ``` +### Isolated API instances + +`OpenFeature::SDK` is a global singleton. Some applications need more than one independent API in a process, for example separately developed modules that each need their own provider, or tests that run in parallel. Require the factory explicitly to create one: + +```ruby +require "open_feature/sdk/isolated" + +api = OpenFeature::SDK::Isolated.create_api +api.set_provider_and_wait(MyProvider.new) +client = api.build_client +client.fetch_boolean_value(flag_key: "my-flag", default_value: false) +``` + +Each instance has its own providers, hooks, evaluation context, event handlers, transaction context propagator and `shutdown`, and shares none of them with `OpenFeature::SDK` or other instances. +Build its clients with `api.build_client`; `OpenFeature::SDK::Client.new` binds to the global API. +Prefer the global API unless you need this. + +A provider instance should be registered with only one API at a time. +Registering a provider that includes `OpenFeature::SDK::Provider::EventEmitter` with a second API raises `ArgumentError`; other providers can't be detected. +Once the first API replaces the provider or shuts down, it can be registered with another. + +A `LoggingHook` created without `logger:` logs to the global API's logger, even when added to an isolated API. Pass `logger:` to use another. + ## Extending ### Develop a provider @@ -443,11 +480,29 @@ You’ll then need to write the provider by implementing the `Provider` duck. ```ruby class MyProvider - def init - # Perform any initialization steps with flag management system here + include OpenFeature::SDK::Provider::EventEmitter + + # Tells the SDK that init emits PROVIDER_READY/PROVIDER_ERROR itself. + def emits_lifecycle_events? = true + + # Optional: a provider without init is READY as soon as it's registered. + # Both arguments are optional; declare only the ones you need. + # `domain` is the domain the provider was bound to, or nil for the default provider. + def init(evaluation_context = nil, domain: nil) + # Perform any initialization steps with flag management system here, then emit PROVIDER_READY. # Return value is ignored # **Note** The OpenFeature spec defines a lifecycle method called `initialize` to be called when a new provider is set. # To avoid conflicting with the Ruby `initialize` method, this method should be named `init` when creating a provider. + emit_event(OpenFeature::SDK::ProviderEvent::PROVIDER_READY) + rescue => e + emit_event(OpenFeature::SDK::ProviderEvent::PROVIDER_ERROR, error_code: OpenFeature::SDK::Provider::ErrorCode::GENERAL, message: e.message) + raise + end + + # Optional: return true if this provider keeps state for a single domain. + # The SDK then raises ArgumentError if the same instance is bound to a second domain. + def domain_scoped? + false end def shutdown @@ -455,8 +510,16 @@ class MyProvider # Return value is ignored end + # Optional: hooks the SDK runs on every evaluation that uses this provider (spec 2.3.1). + # They run after API, client and invocation hooks in the before stage, and first in the after, error and finally stages. + def hooks + [] + end + def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil) # Retrieve a boolean value from provider source + # To signal an error, return ResolutionDetails with an error_code, or raise + # OpenFeature::SDK::EvaluationError.new("message", error_code: OpenFeature::SDK::Provider::ErrorCode::FLAG_NOT_FOUND) end def fetch_string_value(flag_key:, default_value:, evaluation_context: nil) @@ -513,5 +576,11 @@ class MyLoggingHook end ``` +Hooks can read the hook context and hints but not change them: + +- Only `before` hooks can change the evaluation context: return an `EvaluationContext` for the SDK to merge in, or assign `hook_context.evaluation_context`. By the time `after`, `error` and `finally` run, it's a deep-frozen copy, so assigning it or changing its values raises `FrozenError`. Your own context isn't frozen. +- The flag key, the default value, the hints, and the client and provider metadata are frozen copies. Your own objects aren't frozen. +- Only the spec's value types are copied: strings, numbers, booleans, times, hashes and arrays. Other objects, such as a user or a record you put in the context, are passed to hooks as they are. A time is copied but left unfrozen, so `utc` and `localtime` still work, and a hash's default proc isn't copied. + > Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs! diff --git a/docs/reference/sdks/server/rust.mdx b/docs/reference/sdks/server/rust.mdx index 16d324b52..43d9dd9d9 100644 --- a/docs/reference/sdks/server/rust.mdx +++ b/docs/reference/sdks/server/rust.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from rust-sdk. Edits should be made here: https://github.com/open-feature/rust-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Wed Oct 21 2026 11:43:08 GMT-0400 (Eastern Daylight Time) +Last updated at Fri Oct 30 2026 08:17:30 GMT+0000 (Coordinated Universal Time) -->

diff --git a/src/datasets/sdks/sdk-compatibility.json b/src/datasets/sdks/sdk-compatibility.json index c71c786b7..60274cdbe 100644 --- a/src/datasets/sdks/sdk-compatibility.json +++ b/src/datasets/sdks/sdk-compatibility.json @@ -184,8 +184,8 @@ "path": "/docs/reference/sdks/server/go", "category": "Server", "release": { - "href": "https://github.com/open-feature/go-sdk/releases/tag/v1.19.0", - "version": "1.19.0", + "href": "https://github.com/open-feature/go-sdk/releases/tag/v1.20.0", + "version": "1.20.0", "stable": true }, "spec": { @@ -514,7 +514,7 @@ "path": "/docs/reference/sdks/client/swift#tracking" }, "Shutdown": { - "status": "❌", + "status": "✅", "path": "/docs/reference/sdks/client/swift#shutdown" }, "Extending": { @@ -532,13 +532,13 @@ "path": "/docs/reference/sdks/server/ruby", "category": "Server", "release": { - "href": "https://github.com/open-feature/ruby-sdk/releases/tag/v0.6.5", - "version": "0.6.5", + "href": "https://github.com/open-feature/ruby-sdk/releases/tag/v0.8.1", + "version": "0.8.1", "stable": false }, "spec": { - "href": "https://github.com/open-feature/spec/releases/tag/v0.8.0", - "version": "0.8.0" + "href": "https://github.com/open-feature/spec/releases/tag/v0.9.0", + "version": "0.9.0" }, "features": { "Providers": {