You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-10-14] [$175] Workspace - Rules are not enabled when copying Merchant rule to the Collect workspace #102210
Version Number: v9.4.93-0 Reproducible in staging?: Yes Reproducible in production?: N/A - new feature, doesn't exist in prod If this was caught during regression testing, add the test name, ID and link from BrowserStack:#101710 Email or phone of affected tester (no customers): n/a Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.5.1 Safari, iPhone 13 iOS 26.6 App Component: Workspace Settings
Action Performed:
Preconditions: User has a Control workspace (Workspace A) with Rules enabled and created merchant rule
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Identify the pull request that introduced this issue and revert it.
The copy part for Merchant rules (codingRules) copies the merchant rules themselves but never copies/sets areRulesEnabled, so the target lands with the rules data but the Rules feature toggled off. Reverting #101710 would just restore the older, worse "Copy failed" bug (#101456) without fixing the missing flag, so a small roll-forward is the right call.
Assigned: @marcochavezf, @JmillsExpensify, @daledah (approving reviewers of #101710) — already auto-assigned; the PR author is a bot so there is no human author to add. Labels: No changes. DeployBlockerCash is kept (App-side fix). DeployBlocker was not present, so nothing was removed.
📋 Detailed Analysis
Evidence
The bug is staging-only because #101710 is the only change in Deploy Checklist: New Expensify 2026-09-24 that touches this flow. Before it, selecting Merchant rules with a Collect target skipped the Upgrade step entirely and the copy failed outright — the user never reached a completed copy, so the "Rules stayed off" end state was unreachable. The PR added CONTROL_ONLY_COPY_PARTS = new Set<Part>(['rules', 'codingRules']) and short-circuits getControlOnlySelectedParts, which now routes this case through Upgrade → Confirm → a copy that actually succeeds: CopyPolicySettingsUtils.ts#L309-L341.
The PR's own test plan only asserted that the Upgrade step is displayed for Merchant rules ("2. Merchant rules behaves the same") — it never verified the post-copy state of Workspace B, which is exactly where this fails.
The underlying omission is older than this release (identical on production), but it was unreachable in this flow until #101710 unblocked it, which is why it surfaced now as a staging-only regression.
Three places each assume someone else turns Rules on, and nobody does:
The codingRules part copies no feature flag.PARTS_TO_POLICY_FIELDS.rules starts with 'areRulesEnabled', but codingRules maps to ['rules'] only — and that single field is explicitly skipped in buildPolicyFieldPatch because the merchant rules are applied through a dedicated patch instead. Net effect: copying Merchant rules writes zero policy-level fields. See CopyPolicySettings.ts#L48-L67 and the skip at L315-L317.
The merchant-rules patch only writes rules.codingRules, leaving areRulesEnabled untouched on the target: CopyPolicySettings.ts#L430-L437.
The Upgrade step doesn't enable the feature either.bulkUpgradeToCorporate flips type to CORPORATE and sets glCodes/eReceipts/receipt thresholds, but never areRulesEnabled: Policy.ts#L6159-L6206 and getCorporateUpgradeOnyxFields.
So Workspace B ends up Control, with the merchant rules stored under policy.rules.codingRules, but areRulesEnabled still false — the Rules feature reads as off and the copied merchant rules are invisible. Copying Rules (rather than Merchant rules) works precisely because that part carries areRulesEnabled across.
Suggested fix (one line, plus coverage): include the feature flag in the codingRules part so it is copied from the source the same way the rules part does it:
codingRules: ['rules','areRulesEnabled'],
'rules' stays skipped in buildPolicyFieldPatch, so this only adds areRulesEnabled: sourcePolicy.areRulesEnabled (true for any source that has merchant rules) to the target patch, and it automatically gets the right pending-field handling.
Two things to check alongside the fix:
The server-side copy has to persist the same thing for the merchant-rules part, otherwise the server push will flip the toggle back off after the optimistic update.
The same gap exists in the duplicate workspace flow, where areRulesEnabled is derived from the rules selection only and ignores the merchant-rules selection: Policy.ts#L3535 vs L3557. Worth fixing in the same PR.
There is also no test coverage for the codingRules part in tests/actions/CopyPolicySettingsTest.ts, which is how this slipped through — the fix should add one asserting the target ends up with areRulesEnabled: true.
@daledah this issue and/or PR mention a deploy blocker or a regression. Before the payment date, post one of the three options in step 20 of the C+ doc: it was a regression, it was not, or you did not review the offending PR. If you don't post, the default is to reduce payment.
@mallenexpensify This issue is a follow-up to our previous PR and required a BE fix. After the BE fix was deployed, I worked with Melvin on this PR to fix the issue in the offline case.
There are no deploy blockers related to our issue or PR.
I don't think this should be considered a regression from our PR, since the actual root cause was on the BE side, not in the changes introduced by our PR
Activity
applause-bot commentedon Sep 24, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/a2bf935adbdd998b5fbb807e85f16ebc3f22b5dd01639c509f0baabb603b4256
melvin-bot commentedon Sep 24, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #101710
github-actions commentedon Sep 24, 2026
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
melvin-bot commentedon Sep 24, 2026
@marcochavezf @JmillsExpensify @daledah you have been assigned to this deploy blocker because you reviewed the offending PR: #101710
melvin-bot commentedon Sep 24, 2026
💬 A slack conversation has been started in #expensify-open-source
MelvinBot commentedon Sep 24, 2026
🔍 Investigation Summary
Classification: Frontend bug
Causing PR: Fix copy settings from Control to Collect workspace - "Show the Upgrade step when copying rules to a Collect workspace" by @MelvinBot (Medium-High confidence)
Related Issues: Auto - Workspace - Unable to "Copy settings" from Control to Collect workspace (the issue #101710 fixed)
Recommendation: ROLL FORWARD
The copy part for Merchant rules (
codingRules) copies the merchant rules themselves but never copies/setsareRulesEnabled, so the target lands with the rules data but the Rules feature toggled off. Reverting #101710 would just restore the older, worse "Copy failed" bug (#101456) without fixing the missing flag, so a small roll-forward is the right call.Assigned: @marcochavezf, @JmillsExpensify, @daledah (approving reviewers of #101710) — already auto-assigned; the PR author is a bot so there is no human author to add.
Labels: No changes.
DeployBlockerCashis kept (App-side fix).DeployBlockerwas not present, so nothing was removed.📋 Detailed Analysis
Evidence
CONTROL_ONLY_COPY_PARTS = new Set<Part>(['rules', 'codingRules'])and short-circuitsgetControlOnlySelectedParts, which now routes this case through Upgrade → Confirm → a copy that actually succeeds: CopyPolicySettingsUtils.ts#L309-L341.production), but it was unreachable in this flow until #101710 unblocked it, which is why it surfaced now as a staging-only regression.Verification
Affected files (confirmed against staging code):
src/libs/actions/Policy/CopyPolicySettings.ts— owns what each copy part writes to the target policy.src/libs/CopyPolicySettingsUtils.ts— the file #101710 modified (gh pr view 101710 --json files→src/libs/CopyPolicySettingsUtils.ts,tests/unit/CopyPolicySettingsUtilsTest.ts).src/pages/workspace/copyPolicySettings/CopyPolicySettingsUpgradePage.tsx— the Upgrade step, which callsbulkUpgradeToCorporateonly.Root Cause
Three places each assume someone else turns Rules on, and nobody does:
codingRulespart copies no feature flag.PARTS_TO_POLICY_FIELDS.rulesstarts with'areRulesEnabled', butcodingRulesmaps to['rules']only — and that single field is explicitly skipped inbuildPolicyFieldPatchbecause the merchant rules are applied through a dedicated patch instead. Net effect: copying Merchant rules writes zero policy-level fields. See CopyPolicySettings.ts#L48-L67 and the skip at L315-L317.rules.codingRules, leavingareRulesEnableduntouched on the target: CopyPolicySettings.ts#L430-L437.bulkUpgradeToCorporateflipstypetoCORPORATEand setsglCodes/eReceipts/receipt thresholds, but neverareRulesEnabled: Policy.ts#L6159-L6206 andgetCorporateUpgradeOnyxFields.So Workspace B ends up Control, with the merchant rules stored under
policy.rules.codingRules, butareRulesEnabledstillfalse— the Rules feature reads as off and the copied merchant rules are invisible. Copying Rules (rather than Merchant rules) works precisely because that part carriesareRulesEnabledacross.Suggested fix (one line, plus coverage): include the feature flag in the
codingRulespart so it is copied from the source the same way therulespart does it:'rules'stays skipped inbuildPolicyFieldPatch, so this only addsareRulesEnabled: sourcePolicy.areRulesEnabled(true for any source that has merchant rules) to the target patch, and it automatically gets the right pending-field handling.Two things to check alongside the fix:
areRulesEnabledis derived from the rules selection only and ignores the merchant-rules selection: Policy.ts#L3535 vs L3557. Worth fixing in the same PR.There is also no test coverage for the
codingRulespart intests/actions/CopyPolicySettingsTest.ts, which is how this slipped through — the fix should add one asserting the target ends up withareRulesEnabled: true.daledah commentedon Sep 25, 2026
checking now
44 remaining items
melvin-bot commentedon Oct 13, 2026
Payment Summary
Resolving PRs:
Enable Rules optimistically when copying merchant rules #102985
Reviewer: @daledah owed $175 via NewDot
BugZero Checklist (@mallenexpensify)
melvin-bot commentedon Oct 16, 2026
@mallenexpensify Whoops! This issue is 2 days overdue. Let's get this updated quick!
mallenexpensify commentedon Oct 16, 2026
@daledah this issue and/or PR mention a deploy blocker or a regression. Before the payment date, post one of the three options in step 20 of the C+ doc: it was a regression, it was not, or you did not review the offending PR. If you don't post, the default is to reduce payment.
daledah commentedon Oct 19, 2026
@mallenexpensify This issue is a follow-up to our previous PR and required a BE fix. After the BE fix was deployed, I worked with Melvin on this PR to fix the issue in the offline case.
There are no deploy blockers related to our issue or PR.
mallenexpensify commentedon Oct 19, 2026
@daledah can you link to a discussion or details? I'm seeing this issue was created after the offending PR was merged. Thx
daledah commentedon Oct 20, 2026
@mallenexpensify we discussed this here on Slack
I don't think this should be considered a regression from our PR, since the actual root cause was on the BE side, not in the changes introduced by our PR
cc @lakchote @marcochavezf
mallenexpensify commentedon Oct 20, 2026
Payment Summary
Contributor+: @daledah due $175 via NewDot
@daledah please include links about deploy blockers and regressions before payment is due so I can pay quicker.