[Payment due @daledah] Add reasonCode parameter to (some) ResendValidateCode calls - #90726
Conversation
…ntly implemented reasons
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
…validation account merge
Reviewer Checklist
Screenshots/Videos4 validate_account on newly added contact methodScreen.Recording.2026-07-13.at.10.42.52.mov |
daledah
left a comment
There was a problem hiding this comment.
The changes LGTM and tested well
|
@chuckdries could you please merge main to resolve failing check? |
|
🎯 @daledah, thanks for reviewing and testing this PR! 🎉 A payment issue will be created for your review once this PR is deployed to production. If payment is not needed (e.g., regression PR review fix etc), react with 👎 to this comment to prevent the payment issue from being created. |
|
🚧 inimaga has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/inimaga in version: 9.4.34-0 🚀
|
|
🤖 Help site review: no changes required This PR plumbs a I reviewed every help-site article under
These articles cover delivery/troubleshooting, resending, 2FA, contact methods, and scam guidance — not the body copy of the magic-code email or the presence/absence of a sign-in button inside it. Nothing in them describes the old generic line ("someone is trying to log in to your account or access a secure feature"), so none of them become inaccurate as a result of this change. There's no article documenting the reveal-card-details, add-contact-method, or account-validation email copy that this PR now differentiates. Since the changed behavior lives in the emails (not in a documented in-product flow) and no existing article references that copy, there's nothing to update on the help site and I have not opened a draft docs PR. @chuckdries — I did not create a linked help-site PR because no article documents the magic-code email copy this change affects. If you'd like a new article added (e.g. explaining the different magic-code request reasons users may see), let me know and I'll draft one. |
|
Deploy Blocker #96131 was identified to be related to this PR. |
|
Hi @chuckdries. QA team can't test step 8 |
|
Looks like I missed a spot in the Auth PR - there's a codepath in |
|
@chuckdries so, no need to check this PR, right? |
|
@IuliiaHerets correct. The functionality is being removed |
|
@chuckdries, please ping me when we have the follow-up PR. |
|
🚀 Deployed to production by https://github.com/roryabraham in version: 9.4.34-14 🚀
|
|
🤖 Payment issue created: #96238 |
|
🚀 Deployed to production by https://github.com/roryabraham in version: 9.4.34-14 🚀
Bundle Size Analysis (Sentry): |




Explanation of Change
Magic code emails currently show a generic line "This code was requested because someone is trying to log in to your account or access a secure feature". The goal is to show the reason the code was requested (with instance-specific data where applicable) and to omit the sign-in button when the request isn't a login.
To do that, the backend needs to know why a magic code was requested. This PR plumbs a
reasonCode(and, where required, supporting params likereasonCardID) from each App call site that triggers a magic code, throughresendValidateCode/requestValidateCodeAction, into theRESEND_VALIDATE_CODE/REQUEST_NEW_VALIDATE_CODEAPI commands. The backend uses thereasonCodeto build the per-reason email copy and show or hide the signin buttonReason codes covered in this PR:
reasonCodesign_inChooseSSOOrMagicCode,BaseValidateCodeFormvalidate_accountVerifyAccountPageBase(see note — fans out to ~15 account-level gates),BaseOnboardingPrivateDomainadd_contact_methodNewContactMethodConfirmMagicCodePagereveal_card_details(+reasonCardID)ExpensifyCardVerifyAccountPage,TravelCVVVerifyAccountPagenull(explicitly passed)BaseOnboardingWorkEmailValidation,WorkspaceVerifyWorkAccountPage,WorkspaceExpensifyCardVerifyWorkAccountPage(all work-email account merge — not yet implemented)requestValidateCodeAction()with no args)ConfirmDelegateMagicCodePage,UpdateDelegateMagicCodePage,PrivatePersonalDetailsConfirmMagicCodePage,SetDefaultContactMethodConfirmMagicCodePage,ReportVirtualCardFraudVerifyAccountPage,ReportCardLostConfirmMagicCodePage,MissingPersonalDetailsMagicCodePage,IssueNewCardConfirmMagicCodePage,MultifactorAuthentication/ValidateCodePage,MultifactorAuthenticationMainContextType safety:
ResendValidateCodeParamsis a discriminated union.reveal_card_detailsrequires areasonCardID; the other reasons forbid extra params;nullis a temporary escape hatch (ResendValidateCodeNotYetImplementedParams) for the one flow whose reason isn't modeled yet. This makes it a compile error to request a card-reveal code without a card ID.Note
VerifyAccountPageBasecoverage is broad. It exposes nosendValidateCodeprop — thevalidate_accountreason is set internally — so the single change there covers every account-level one-time validation gate that wraps it (~15 routes): add delegate/copilot, enable 2FA, company-card feed, bank account for wallet/reimbursements, invoicing bank account, workspace domain, international deposit country, travel access, create/confirm money request, report/expense-report/search actions, and enable wallet. Testing one of these wrappers exercises them all; the rest only need a spot check.Note
This is intentionally not a complete migration of every magic-code call site. Auth/Web-E treat an empty/
nullreasonCodeas legacy and fall back to the generic copy, so un-migrated callers are unaffected. A follow-up will cover the remaining reasons and then tightenreasonCodeto required on the backend.Known deferred gate: "Verify a newly added contact method" (
ContactMethodDetailsPage) is avalidate_account-semantics email that this PR leaves on the generic fallback. It callsrequestContactMethodValidateCode, which writes the separateREQUEST_CONTACT_METHOD_VALIDATE_CODEcommand — a different command/param type than theRESEND_VALIDATE_CODE/REQUEST_NEW_VALIDATE_CODEpaths this PR plumbs. Carrying a reason there requires plumbing that third command, deferred to the follow-up.Fixed Issues
$ https://github.com/Expensify/Expensify/issues/623748
PROPOSAL:
Tests
1.
sign_in— login via magic code (resend)BaseValidateCodeForm).2.
sign_in— SSO "Use magic code"ChooseSSOOrMagicCode).3.
add_contact_method— add a new contact method4.
validate_account— validate the newly-added contact method5.
reveal_card_details— virtual Expensify cardNNNNmatches the last four of the card.6.
reveal_card_details— Travel CVV7.
validate_account— account-level gate viaVerifyAccountPageBase(represented by Enable 2FA)Every account-level gate in the coverage note routes through
VerifyAccountPageBase, so this one case represents all 15. 2FA is the easiest to reach.settings/security/delegate/verify-account) and confirm identical copy, proving the shared path.8.
validate_account— onboarding private domain (BaseOnboardingPrivateDomain)This page only renders during onboarding when the account is on a private domain that already has at least one accessible workspace, and of course if the account is unvalidated. That's tricky because if the domain is validated, App will challenge you for a magic code at signin time because your account is considered domainControlled. So you need a private domain that is not validated but you can actually receive emails to.
Offline tests
N/A
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, 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.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
1 sign_in
reasonCode.test.sign_in.mp4
3 add_contact_method
reasonCode.test.add_contact_method.mp4
4 validate_account on newly added contact method
reasonCode.test.validate_account.new.contact.method.mp4
5 reveal_card_details virtual card
reasonCode.test.reveal_card_details.mp4
6 reveal_card_details Travel CVV
Note that in the dev environment we don't actually see a CVV because the travel setup scripts don't create a card in marqeta. The important thing is the magic code page dismissed rather than showing an errorreasonCode.test.reveal_card_details.travel.CVV.mp4
7 validate_account one-time feature gate (2fa enablement)
reasonCode.test.validate_account.one-time.gate.2fa.enable.mp4
8 validate_account private domain onboarding
reasonCode.test.validate_account.private.domain.mp4