Skip to content

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

Open
Cal-L wants to merge 18 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 18 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 flags are computed and persisted across upgrades and offline fetch failures; behavior is heavily tested but affects a widely used controller path.

Overview
Remote feature flag layering — Apps can pass optional defaultFeatureFlags (not persisted) into RemoteFeatureFlagController; Wallet exposes the same via instanceOptions.remoteFeatureFlagController.defaultFeatureFlags.

Persisted processed remote — State gains processedRemoteFeatureFlags (persisted) as the remote layer after threshold/version processing. Effective remoteFeatureFlags are always derived via #getEffectiveFeatureFlags: defaults < processed remote < local overrides. Overrides and cache updates write through that helper instead of mutating remoteFeatureFlags directly.

Upgrade and fetch behavior — If processedRemoteFeatureFlags was never saved, cache is invalidated to force a refetch; pre-upgrade installs still use the old persisted remoteFeatureFlags for first paint while defaults apply underneath. When a fetch fails in that state, the controller can hydrate processedRemoteFeatureFlags from persisted rawRemoteFeatureFlags without advancing cacheTimestamp so retries still happen.

Tests cover defaults, precedence, migration, failed-fetch hydration, and threshold edge cases (no matching group, nameless threshold entries).

Reviewed by Cursor Bugbot for commit 2b81ab9. 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 8576196. Configure here.

getMetaMetricsId,
clientVersion,
prevClientVersion,
defaultFeatureFlags = {},

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.

Ability for platforms to provide feature flag defaults


// Force a refetch when processed remote has never been persisted so the
// new field is populated (from the API).
const shouldForceRefetch =

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.

Force refetch if processed remote feature flags do not exist

!hasPersistedProcessedRemote || hasClientVersionChanged;

// Derive effective flags from defaults + processed + overrides.
const remoteFeatureFlags = {

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.

Prioritize feature flags in this order

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