[NO QA] Adds logging to MFA flow#84058
Conversation
Adds breadcrumb tracing at key decision points in the MFA state machine to provide a chronological trail in Sentry when issues occur in production (failed biometrics, stuck flows, backend errors).
Add breadcrumbs to the navigation hook and authorize transaction page with separate categories (3ds.navigation, 3ds.authorize) for filtering. Inline breadcrumb helpers directly in consuming files.
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.
|
Resolve conflict in CONST/index.ts — keep both MFA/3DS breadcrumb categories and new module.init/script.load categories from main.
|
@dukenv0307 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] |
rafecolton
left a comment
There was a problem hiding this comment.
Prefer MFA everywhere to Mfa, since it is an acronym.
| import type {AuthTypeName, MultifactorAuthenticationReason} from '@libs/MultifactorAuthentication/Biometrics/types'; | ||
| import CONST from '@src/CONST'; | ||
|
|
||
| const EXPECTED_FAILURE_REASONS = new Set<MultifactorAuthenticationReason>([ |
There was a problem hiding this comment.
From the context, specifically not seeing "already reviewed" in this list, I think I know what you mean by expected vs unexpected. However, it's a bit of an overloaded term, since there are actually more like three types in this regard:
- Errors that are known and we think the user is likely to encounter
- Errors that are known and we think the user is not likely to encounter
- Errors that are not known (e.g. 5xx)
My suggestion is:
- Rename
EXPECTED_FAILURE_REASONStoROUTINE_FAILURES. Then category (2) above can beANOMALOUS_FAILURES, and (3) isUNCLASSIFIED_FAILURES. - Create a sub-grouping within the type definitions so you can pull that directly and don't need to duplicate it here. This can be in addition or perhaps instead of the existing groupings e.g.
CHALLENGE,EXPO, etc.
|
|
||
| function trackMfaFlowOutcome(context: MfaFlowOutcomeContext): void { | ||
| try { | ||
| const isExpectedFailure = !context.isSuccessful && context.reason !== undefined && EXPECTED_FAILURE_REASONS.has(context.reason); |
There was a problem hiding this comment.
Per above comment, I suggest renaming this to isRoutineFailure
| }); | ||
|
|
||
| if (level === 'error') { | ||
| Log.hmmm(`[MFA] ${eventMessage}`, extra); |
There was a problem hiding this comment.
Let's use warn here so that if we get a lot for the same reason, it'll trigger a bugbot
| }; | ||
|
|
||
| const onSilentlyDenyTransaction = () => { | ||
| addBreadcrumb('Silent deny (back button)', {transactionID}, 'warning'); |
There was a problem hiding this comment.
NAB "back button" could get confused with the browser back button
| addBreadcrumb('Silent deny (back button)', {transactionID}, 'warning'); | |
| addBreadcrumb('Silent deny (user canceled flow)', {transactionID}, 'warning'); |
…lds, add Sentry fingerprint by reason
rafecolton
left a comment
There was a problem hiding this comment.
You have some CI failures, otherwise LGTM
…ILURES sets tsgo infers narrow literal unions for Set elements, causing .has() to reject the wider MultifactorAuthenticationReason type. Adding an explicit ReasonValue type parameter to both sets resolves the mismatch.
rafecolton
left a comment
There was a problem hiding this comment.
Thank you! @chuckdries final review is yours
|
|
||
| if (cancel) { | ||
| Log.info('[useNavigateTo3DSAuthorizationChallenge] Ignoring navigation - effect was cleaned up while GetTransactionsPending3DSReview was in-flight'); | ||
| addBreadcrumb('Skipped - effect cancelled', {transactionID: transactionPending3DSReview.transactionID}); |
There was a problem hiding this comment.
Looks good overall, but now that we have the breadcrumb is there a reason to keep the logs that say the same thing?
|
🚧 @rafecolton has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
Reviewer Checklist
Screenshots/Videos |
|
🚧 @chuckdries 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/chuckdries in version: 9.3.34-0 🚀
|
|
🚀 Deployed to production by https://github.com/luacmartins in version: 9.3.34-2 🚀
|


Explanation of Change
Adds observability instrumentation to the MFA and 3DS transaction authorization flows. This includes:
trackMfaFlowOutcome— sends aSentry.captureMessageevent plusLog.info/Log.hmmmcalls on every flow completion (success or failure), with full context (scenario, reason, httpStatusCode, auth method, state flags)mfa,3ds.navigation,3ds.authorize) and Sentry tags (mfa_scenario,mfa_error_reason)scenarioNameadded to MFA state so the outcome tracker knows which scenario was executed (preserved across re-registrations)messagefield added toRegistrationChallengeResponseandAuthenticationChallengeResponsetypes for richer error contextKnown limitations (to be addressed in follow-up work)
authorization,authenticated,credential,key,secret,signature,token, etc. This causes many MFA-related error details to be redacted because they naturally contain words like "authorization". Needs investigation into adjusting the Sentry blocklist configuration.Sentry.captureMessage+ breadcrumbs. Sentry also supports lightweight Logs (simple messages without accumulated breadcrumb context). Some of the current instrumentation could be moved to Logs for lower overhead, while keepingcaptureMessageonly for cases where full breadcrumb context is valuable.Fixed Issues
$ #82705
Tests
N/A — This is a logging/observability-only change. No user-facing behavior is modified.
Offline tests
N/A — No offline behavior changes. MFA breadcrumbs and Sentry events are fire-and-forget; they do not affect offline functionality.
QA Steps
N/A — No user-facing behavior changes. This PR only adds internal logging and Sentry instrumentation.
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