docs: update remote feature flag threshold API#176
Closed
asalsys wants to merge 1 commit into
Closed
Conversation
Document featureFlagThresholdGroups, canonical ID as the default threshold
segmentation identifier, and removal of the legacy { name, value } wrapper.
Co-authored-by: Cursor <cursoragent@cursor.com>
pull Bot
pushed a commit
to dmrazzy/core
that referenced
this pull request
Jul 2, 2026
…y and track threshold groups (MetaMask#9289) ## Summary - **BREAKING:** Threshold feature flags now return the selected `value` directly from `remoteFeatureFlags` instead of a `{ name, value }` wrapper object. - Add optional `featureFlagThresholdGroups` state field (`Record<string, string>`) that maps feature flag names to their selected threshold group name when the selected threshold entry includes `name`. - Remove `normalizeThresholdValue` and the legacy `{ name, value }` wrapper fallback. ## References - Fixes [MCWP-655](https://consensyssoftware.atlassian.net/browse/MCWP-655) ## Motivation Separating the processed flag value from threshold group metadata makes it easier for consumers to use threshold flags as plain values (booleans, objects, etc.) without unwrapping. The new `featureFlagThresholdGroups` field provides explicit access to A/B group assignment when the selected threshold entry includes `name`. Entries that only define `thresholdName` (for example in `thresholdVersion: 2` configs) still resolve to the selected `value`, but do not populate `featureFlagThresholdGroups` because that field is driven by `name`. ## Migration Consumers that previously read threshold group names from `remoteFeatureFlags[flagName].name` should instead: 1. Read the flag value directly from `remoteFeatureFlags[flagName]`. 2. Read the threshold group name from `featureFlagThresholdGroups[flagName]` when available (populated when the selected threshold entry includes `name`). **Before:** ```ts const flag = remoteFeatureFlags.myThresholdFlag; // { name: 'groupB', value: { enabled: true } } const groupName = flag.name; const value = flag.value; ``` **After:** ```ts const value = remoteFeatureFlags.myThresholdFlag; // { enabled: true } const groupName = featureFlagThresholdGroups.myThresholdFlag; // 'groupB' ``` ## Related - Documentation: [MetaMask/contributor-docs#176](MetaMask/contributor-docs#176) ## Test plan - [x] `yarn workspace @metamask/remote-feature-flag-controller run test` — all tests pass with 100% coverage - [x] Threshold flags return the selected `value` directly from `remoteFeatureFlags` - [x] Threshold flags populate `featureFlagThresholdGroups` when the selected entry includes `name` - [x] Threshold flags with only `thresholdName` return the value directly and leave `featureFlagThresholdGroups` empty - [x] Stale `featureFlagThresholdGroups` entries are cleaned up when flags are removed from the server response [MCWP-655]: https://consensyssoftware.atlassian.net/browse/MCWP-655?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Breaking change to the public shape of threshold flag values affects all consumers of `remoteFeatureFlags`; persisted state gains a new field but assignment logic is otherwise unchanged. > > **Overview** > **BREAKING:** Threshold/A/B flags in `remoteFeatureFlags` now expose the selected entry’s **`value` only** (string, boolean, object, etc.) instead of a `{ name, value }` wrapper. Group assignment moves to a new optional persisted state field **`featureFlagThresholdGroups`** (`flagName → group name`) when the winning threshold item has a `name`. > > Processing drops **`normalizeThresholdValue`** and **`ThresholdVersion`** branching—legacy wrappers and “direct value vs wrapper” version handling are gone; threshold arrays are resolved the same way regardless of `thresholdVersion`. On each fetch, **`featureFlagThresholdGroups` is rebuilt** from the current server payload so entries for removed flags are cleared (covered by tests). > > **Migration:** read values from `remoteFeatureFlags[flag]`; read group names from `featureFlagThresholdGroups[flag]` when present. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 98b74a2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Updates remote feature flags documentation to reflect the
RemoteFeatureFlagControllerAPI changes in MetaMask/core#9325, MetaMask/core#9289:valuedirectly fromremoteFeatureFlags(no{ name, value }wrapper).featureFlagThresholdGroupswhen the winning threshold entry includesname.idTypeon threshold entries (canonicalby default,metametricsfor legacy MetaMetrics segmentation).Test plan
RemoteFeatureFlagControllerbehavior in core PR #9325Made with Cursor