Skip to content

Feat: Seed remote feature flag controller with default flags - #9747

Open
Cal-L wants to merge 12 commits into
mainfrom
feat/seed-defaults-remote-feature-flag-controller
Open

Feat: Seed remote feature flag controller with default flags#9747
Cal-L wants to merge 12 commits into
mainfrom
feat/seed-defaults-remote-feature-flag-controller

Conversation

@Cal-L

@Cal-L Cal-L commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Explanation

This is part of an effort to keep the RemoteFeatureFlagController as the source of truth for feature flags. As part of that effort, we've added a new optional constructor arg named defaultFeatureFlags, which will be provided by the platform apps. Under the hood, the controller will account for these flags when processing the effective flags that the consumers will use. The order of priority for the flags are - default flags > remote flags > override flags.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Changes how effective feature flags are computed and persisted across sessions, including migration paths for existing state; behavior is well-tested but touches a central controller used broadly by clients.

Overview
Adds optional defaultFeatureFlags on RemoteFeatureFlagController (and instanceOptions.remoteFeatureFlagController.defaultFeatureFlags in Wallet) so platform apps can supply client-side defaults that are not persisted. Effective remoteFeatureFlags are now built with precedence defaults → processed remote → local overrides, via a shared #getEffectiveFeatureFlags path used on init, cache updates, and override APIs.

Introduces persisted processedRemoteFeatureFlags so the remote layer can be stored and recombined with defaults and overrides (including when removing or clearing overrides). #updateCache writes both processed and effective layers and supports optional skips for raw persistence and cache timestamp refresh.

Upgrade / migration: if processedRemoteFeatureFlags was never saved, the controller invalidates the cache to force a refetch, keeps the prior effective blob for first paint (with defaults and overrides layered on top), and on fetch failure can hydrate processed state from persisted rawRemoteFeatureFlags without advancing the cache timestamp so a later API retry remains possible.

Reviewed by Cursor Bugbot for commit 08f4bfe. Bugbot is set up for automated code reviews on this repo. Configure here.

@Cal-L
Cal-L requested review from a team as code owners July 31, 2026 18:55
@Cal-L
Cal-L temporarily deployed to default-branch July 31, 2026 18:56 — with GitHub Actions Inactive
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
includeInDebugSnapshot: true,
usedInUi: false,
},
processedRemoteFeatureFlags: {

@Cal-L Cal-L Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This persisted state is the processed version of REMOTE feature flags, excluding defaults and overrides. Used for flag reconstruction on controller creation, preventing the need for a deconstruction.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a18da3c. Configure here.

* fails, falls back to processing persisted `rawRemoteFeatureFlags` so the
* new field can still be populated offline.
*
* @returns A promise that resolves to the current set of feature flags.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overrides wipe pre-upgrade remote flags

High Severity

When processedRemoteFeatureFlags is missing, first paint keeps the old effective blob, but #processedRemoteFeatureFlags is set to {}. setFlagOverride, removeFlagOverride, and clearAllFlagOverrides rebuild effective flags from that empty private field, so any override call before fetch or raw hydration drops persisted remote flags.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a18da3c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant