Repository navigation
Fix/align workspace selector logic v2 - #102844
roryabraham merged 14 commits into
Conversation
…430-fix/align-workspace-selector-logic' + fixed
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
Home quick bar and Search header Create menu bypassed the hook and ignored the domain preferred-workspace lock (Expensify#102130). The hook now resolves the default workspace itself via a scalar selector, so callers no longer pass groupPoliciesWithChatEnabled.
|
@MelvinBot are you able to run web only ad hoc on this PR ? |
|
@MelvinBot not what I asked for. Run a web ad hoc build so a human can test scenarios you can't |
|
Sorry, I misread your first request. I can't start the ad hoc build. The Build and deploy apps for testing workflow only runs when an Expensify employee with write access dispatches it. That person must also confirm they reviewed the PR for malicious code. This PR comes from a fork, so that review is a human check I shouldn't sign off on. An Expensify employee can start a web-only build by running that workflow with these inputs:
The workflow comments on this PR when it starts and posts the web link when the build is ready. |
|
@MelvinBot review please |
PR reviewI found one likely regression and two smaller issues. The rest looks good: all five entry points now share one code path, the preferred workspace is read by key, and 1. Empty Reports view now reads policies from the Search snapshot (likely regression)
Before this PR, the empty view built the eligible list and the policy passed to Possible effects in the empty Reports view:
Suggested fix: In I traced this in the code but didn't confirm it at runtime. 2. Two entry points ignore
|
|
@sobitneupane Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
cc. @trjExpensify could you please take a look @ vids and test steps and confirm they're as expected ? |
JmillsExpensify
left a comment
There was a problem hiding this comment.
Mostly cleanup here. LGTM
|
@jmusial I could not verify Scenario 3. The empty report is created in the default workspace instead of the preferred workspace. Screen.Recording.2026-10-08.at.20.25.35.mov |
|
🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
I can help review this PR. Slack |
| shouldHandleNavigationBack = true, | ||
| shouldSkipEmptyReportConfirmation = false, | ||
| }: UseCreateReportParams): UseCreateReportResult { | ||
| const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); |
There was a problem hiding this comment.
@jmusial Can we remove this comment? I don't think it's necessary.
| // Read the preferred workspace by key rather than searching the caller's list, so the lock does not depend on | ||
| // how (or whether) a caller filtered its candidates. Same pattern as useDefaultExpensePolicy. |
There was a problem hiding this comment.
@jmusial Can we remove this comment? I don't think it's necessary.
|
|
||
| const defaultChatEnabledPolicy = getDefaultChatEnabledPolicy(groupPoliciesWithChatEnabled as Array<OnyxEntry<OnyxTypes.Policy>>, activePolicy); | ||
| // A domain security group can lock members to a preferred workspace. When that workspace can take reports it wins over | ||
| // the active policy and the selector is skipped. An ineligible preferred workspace (not a member, wrong type) falls back to the normal rules. |
There was a problem hiding this comment.
@jmusial Can we remove this comment? I don't think it's necessary.
|
Scenario 1: default workspace 3rd or later in the list Screen.Recording.2026-10-14.at.11.50.16.movScenario 2: domain lock + billing restriction Screen.Recording.2026-10-14.at.11.53.38.movScenario 3: domain lock beats the default workspace Screen.Recording.2026-10-14.at.12.05.33.movScenario 4: domain lock with a personal default (#101560 (comment)) Screen.Recording.2026-10-14.at.12.14.08.movScenario 5: domain lock on every Create report entry point Screen.Recording.2026-10-14.at.12.17.39.movScenario 6: billing-restricted default with other workspaces (selector expected) Screen.Recording.2026-10-14.at.12.21.44.mov |
Reviewer Checklist
Screenshots/VideosScenario 1: default workspace 3rd or later in the list Screen.Recording.2026-10-14.at.11.50.16.movScenario 2: domain lock + billing restriction Screen.Recording.2026-10-14.at.11.53.38.movScenario 3: domain lock beats the default workspace Screen.Recording.2026-10-14.at.12.05.33.movScenario 4: domain lock with a personal default (#101560 (comment)) Screen.Recording.2026-10-14.at.12.14.08.movScenario 5: domain lock on every Create report entry point Screen.Recording.2026-10-14.at.12.17.39.movScenario 6: billing-restricted default with other workspaces (selector expected) Screen.Recording.2026-10-14.at.12.21.44.mov |
|
@jmusial Could you check my comment above? |
|
@jmusial could you sync with main? |
|
@roryabraham all yours |
|
🚧 roryabraham has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.5.15-1 🚀
|
|
No help site update needed. This PR makes Create report behave the way the articles already describe: it opens the report on the default or Preferred Workspace without asking you to pick one. Articles checked
|
|
Hi @jmusial. Can you please clarify how to set up the Billing Restricted Workspace in the Admin Domain account? |
|
@jmusial We were able to test Scenarios 1,3 and 5. Scenario 2: domain lock + billing restriction, Scenario 4: domain lock with a personal default and Scenario 6: billing-restricted default with other workspaces (selector expected) Scenario 4: domain lock with a personal default - unable to find the personal workspace in OD |
I think the workspace needs to be owned by an account that is past due and past its billing grace period. |
|
@jmusial applause.expensifail.com domain accounts does not have have past its billing grace period accounts. |
|
🚀 Deployed to production by https://github.com/grgia in version: 9.5.15-3 🚀
Bundle Size Analysis (Sentry): |










Explanation of Change
Explanation of Change
A follow-up to #98973 (details), and the re-land of #101430, which was reverted in #102134 after deploy blocker #102130.
Aligns "Create report" with the intended workspace selector rules:
.slice(0, 2), so a default workspace that is 3rd or later in the list creates the report directly.Behaviour change vs production: domain-locked users who see the workspace selector today will stop seeing it. This is intended.
What changed since #101430
groupPoliciesWithChatEnabledlist for it. When the preferred workspace wasn't in that list, the lock silently did nothing, which is the [Due for payment 2026-10-01] Creating new report via FAB automatically uses default WS, not the Preferred one. #102130 symptom. It is now read directly and validated with the newcanCreateReportOnPolicy. A membership-only stub falls back to the normal rules.useCreateReportresolves the default workspace itself. It usesgetDefaultChatEnabledPolicySelectionselector, and callers no longer passgroupPoliciesWithChatEnabled. Each caller used to build that list differently; for example, the empty Reports view built it without the user's login. This also avoids deep-comparing every eligible policy on eachpolicy_update, which the FAB started doing once.slice(0, 2)was dropped.useCreateReporttoo.Fixed Issues
$ #101560
PROPOSAL:
Tests
Setup for domain-locked scenarios
Account on a verified domain, member of 3+ workspaces, none owned. A domain admin opens Domains > [domain] > Groups > [account's group], turns on "Preferred Workspace" and picks workspace B. The account's default workspace (Settings > Workspaces, "Default" badge) is a different workspace, A.
Original issue (#101560)
Scenario 1: default workspace 3rd or later in the list
Scenario 2: domain lock + billing restriction
Deploy blocker (#102130)
Scenario 3: domain lock beats the default workspace
Scenario 4: domain lock with a personal default (#101560 (comment))
New in this PR
Scenario 5: domain lock on every Create report entry point
Showing selector example
Scenario 6: billing-restricted default with other workspaces (selector expected)
Offline tests
N/A
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
MacOS: Chrome / Safari
Scenarios 1 - 5
Screen.Recording.2026-10-07.at.12.55.16.mov
Scenario 6
Screen.Recording.2026-10-07.at.12.59.54.mov