feat(feature-flags): migrate 3 env-flags to AppConfig-backed runtime flags#5086
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Table row ordering no longer reads Mothership beta replaces
UI: Tests mock Reviewed by Cursor Bugbot for commit 850bd7e. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
@greptile review |
Greptile SummaryMigrates three startup-time env flags (
Confidence Score: 4/5Safe to merge for deployments using global enable/disable flags; per-user targeting of mothership-beta will be silently incomplete in three call paths. The core migration is well-structured: AppConfig schema fixes are correct, fallback env vars are preserved, and the fractional-ordering flag is consistently resolved at each async call site. The
Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Browser
participant TablePage as TablePage (RSC)
participant FF as feature-flags.ts
participant AC as AppConfig (~30s TTL)
participant Table as Table (Client)
participant VFS as WorkspaceVfs
participant DC as getE2BDocFormat
Browser->>TablePage: GET /tables/[id]
TablePage->>FF: "isFeatureEnabled('workflow-columns', {userId})"
FF->>AC: fetchAppConfigProfile (cached)
AC-->>FF: FeatureFlagsConfig
FF-->>TablePage: true/false
TablePage->>Table: workflowColumnsEnabled prop
Table-->>Browser: renders (workflow cols visible or hidden)
Note over VFS: materialize(workspaceId, userId)
VFS->>FF: "isFeatureEnabled('mothership-beta', {userId})"
FF->>AC: fetchAppConfigProfile (cached)
AC-->>FF: FeatureFlagsConfig
FF-->>VFS: betaEnabled (per-user check works)
VFS->>VFS: _betaEnabled stored for request
Note over DC: getE2BDocFormat(fileName)
DC->>FF: isFeatureEnabled('mothership-beta') no userId
FF->>AC: fetchAppConfigProfile (cached)
AC-->>FF: FeatureFlagsConfig
FF-->>DC: false if userIds-only targeting
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Browser
participant TablePage as TablePage (RSC)
participant FF as feature-flags.ts
participant AC as AppConfig (~30s TTL)
participant Table as Table (Client)
participant VFS as WorkspaceVfs
participant DC as getE2BDocFormat
Browser->>TablePage: GET /tables/[id]
TablePage->>FF: "isFeatureEnabled('workflow-columns', {userId})"
FF->>AC: fetchAppConfigProfile (cached)
AC-->>FF: FeatureFlagsConfig
FF-->>TablePage: true/false
TablePage->>Table: workflowColumnsEnabled prop
Table-->>Browser: renders (workflow cols visible or hidden)
Note over VFS: materialize(workspaceId, userId)
VFS->>FF: "isFeatureEnabled('mothership-beta', {userId})"
FF->>AC: fetchAppConfigProfile (cached)
AC-->>FF: FeatureFlagsConfig
FF-->>VFS: betaEnabled (per-user check works)
VFS->>VFS: _betaEnabled stored for request
Note over DC: getE2BDocFormat(fileName)
DC->>FF: isFeatureEnabled('mothership-beta') no userId
FF->>AC: fetchAppConfigProfile (cached)
AC-->>FF: FeatureFlagsConfig
FF-->>DC: false if userIds-only targeting
|
Greptile SummaryThis PR migrates three startup-time env-gate flags (
Confidence Score: 3/5The core flag migration and schema fix are correct, but the embedded-table path is a behavioral regression that would silently suppress workflow columns for any user who has the flag enabled. The embedded
Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant TablePage as TablePage (Server)
participant AppConfig
participant Table as Table (Client)
participant TableGrid
participant NewColDrop as NewColumnDropdown
participant ResourceContent as resource-content (Client)
TablePage->>AppConfig: "isFeatureEnabled('workflow-columns', {userId})"
AppConfig-->>TablePage: boolean
TablePage->>Table: "workflowColumnsEnabled={boolean}"
Table->>TableGrid: "workflowColumnsEnabled={boolean}"
TableGrid->>NewColDrop: "workflowColumnsEnabled={boolean}"
Note over ResourceContent: Embedded table path (regression)
ResourceContent->>Table: workspaceId, tableId, embedded
Note over Table: workflowColumnsEnabled defaults to false
Table->>TableGrid: "workflowColumnsEnabled=false"
TableGrid->>NewColDrop: "workflowColumnsEnabled=false"
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant TablePage as TablePage (Server)
participant AppConfig
participant Table as Table (Client)
participant TableGrid
participant NewColDrop as NewColumnDropdown
participant ResourceContent as resource-content (Client)
TablePage->>AppConfig: "isFeatureEnabled('workflow-columns', {userId})"
AppConfig-->>TablePage: boolean
TablePage->>Table: "workflowColumnsEnabled={boolean}"
Table->>TableGrid: "workflowColumnsEnabled={boolean}"
TableGrid->>NewColDrop: "workflowColumnsEnabled={boolean}"
Note over ResourceContent: Embedded table path (regression)
ResourceContent->>Table: workspaceId, tableId, embedded
Note over Table: workflowColumnsEnabled defaults to false
Table->>TableGrid: "workflowColumnsEnabled=false"
TableGrid->>NewColDrop: "workflowColumnsEnabled=false"
Reviews (2): Last reviewed commit: "feat(feature-flags): migrate 3 env-flags..." | Re-trigger Greptile |
| ): Promise<SandboxFile[]> { | ||
| const sandboxFiles: SandboxFile[] = [] | ||
| let totalSize = 0 | ||
| const betaEnabled = await isFeatureEnabled('mothership-beta') |
There was a problem hiding this comment.
mothership-beta evaluated without user context in several callers
isFeatureEnabled('mothership-beta') is called here (and in workflow-alias-resolver.ts and getE2BDocFormat in doc-compile.ts) without a userId. If the flag is later configured with a userIds allowlist in AppConfig, beta-enabled users would be denied access via these code paths even though WorkspaceVFS.materialize would correctly grant it. The per-user semantics promised in WorkspaceVFS are silently absent anywhere the call chain doesn't have a userId available — worth documenting or passing through as a future hardening item.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4745d51. Configure here.

Summary
isTablesFractionalOrderingEnabled,isMothershipBetaFeaturesEnabled, andisWorkflowColumnsEnabledClientfrom startup-time env gates inenv-flags.tsto AppConfig-backed runtime flags infeature-flags.tsfeature-flags.tsto match the existing AppConfig JSON schema: flag names are top-level keys (noflagswrapper), and admin gating isadminEnablednotadminsworkflow-columnsflag moves from aNEXT_PUBLIC_*build-time bake to server-side resolution in the table page, threaded as a prop toNewColumnDropdownmothership-betaflag now resolves per-user inWorkspaceVfs.materializewhere userId is in scopetables-fractional-orderingflag replaced inline at each async call site inrows/service.tsandrows/ordering.ts;buildRowOrderBySqlstays synchronous via afractionalOrderingEnabled: booleanparameterisFeatureEnabledreturningfalseAppConfig document format (freeform profile, no
flagswrapper):{ "tables-fractional-ordering": { "enabled": true, "adminEnabled": false, "orgIds": [], "userIds": [] }, "mothership-beta": { "enabled": true, "adminEnabled": false, "orgIds": [], "userIds": [] }, "workflow-columns": { "enabled": true, "adminEnabled": false, "orgIds": [], "userIds": [] } }Type of Change
Testing
Tested manually. Lint and
check:api-validation:strictpass.Checklist