Skip to content

[Due for payment 2026-10-27] [$175] Android - Concierge opens before onboarding is completed #102956

Closed

Description

@applause-bot

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: 9.5.2-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #101558
Email or phone of affected tester (no customers): jsoidjndoiniodnsjojd@gmail.com
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: Samsung Galaxy S25 FE / Android 16
App Component: Other

Action Performed:

  1. Go to staging.new.expensify.com/concierge
  2. Log in with new Gmail account.

Expected Result:

Concierge will open after onboarding is completed.

Actual Result:

Concierge opens before onboarding is completed.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome Safari

Screenshots/Videos

Bug7277424_1791169057649.Screen_Recording_20261005_105632_Permission_controller.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Mita Rachim
Bug ID: 7277424

Upwork Automation - Do Not Edit
Issue OwnerCurrent Issue Owner: @mallenexpensify

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 5, 2026
  2. applause-bot commented on Oct 5, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/a00190b2a2ea6dc4fb7d4d44617caeaf74ddcfe5feda70cfb9f45abee3b40c9d

  3. MelvinBot commented on Oct 5, 2026

    @MelvinBot
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Android and iOS, a new user who opens /concierge and then signs up sees the Concierge chat before onboarding is completed.

    What is the root cause of that problem?

    This bug already exists in production. Open a deep link captured before onboarding instead of dropping it did not cause it.

    1. Native keeps the /concierge screen through sign-in. On a native cold start, react-navigation builds its first state from the launch URL. Native loads its screens synchronously, so that state survives sign-in. After sign-up, the signed-in screens rebuild from it with ConciergePage on top. Web loads its screens lazily, which drops that state, so ConciergePage never mounts on web.
    2. ConciergePage never checks onboarding. It opens the Concierge chat with shouldDismissModal: true as soon as report data has loaded. This usually happens before the onboarding flow opens.
    3. HybridApp skips the onboarding guard. OnboardingGuard lets navigation through when isHybridAppOnboardingCompleted !== true. The Concierge navigation is not blocked.
    Code references

    What changes do you think we should make in order to solve the problem?

    In ConciergePage, skip the navigation while onboarding is still pending:

    1. Read the raw NVP_ONBOARDING.hasCompletedGuidedSetupFlow value. Do not use hasCompletedGuidedSetupFlowSelector, which treats an empty value as completed.
    2. In the focus effect, return early when the value is false, and add it to the effect's dependencies.

    After onboarding, the deep link that openReportFromDeepLink holds opens the Concierge chat through navigateAfterOnboarding. If ConciergePage is still mounted, its effect runs again. The "already on this route" check in Link.ts stops the chat from opening twice.

    What alternative solutions did you explore? (Optional)

    • Fix the root cause in navigation. Add a getInitialURL to linkingConfig that returns null when the user is signed out and the route is not public. This also covers other signed-in-only links opened on a cold start, such as /track-expense. It is riskier. Magic links, /transition, SAML, and connection-complete pages need QA.
    • Narrow the OnboardingGuard HybridApp bypass so it does not apply while NewDot onboarding is pending. This change affects more flows.
    Confidence and verification

    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/102956) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.


    view run · no recording available

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 5, 2026
  5. melvin-bot commented on Oct 5, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @QichenZhu (External)

  6. changed the title [-]Android & iOS - Concierge opens before onboarding is completed[/-] [+][$175] Android & iOS - Concierge opens before onboarding is completed[/+] on Oct 5, 2026
  7. melvin-bot commented on Oct 5, 2026

    @melvin-bot
  8. bonnhatnguyen commented on Oct 5, 2026

    @bonnhatnguyen
    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Android and iOS native platforms, when a new user opens staging.new.expensify.com/concierge while logged out and completes sign-up/sign-in, the Concierge chat opens prematurely before the onboarding flow is completed.


    What is the root cause of that problem?

    1. Native retains [CONCIERGE] in the initial route state:
      On a native cold start via the /concierge deep link, React Navigation builds its root navigation state from the launch URL. In AppNavigator.native.tsx, screen modules are required synchronously, preserving [CONCIERGE] (ConciergePage) at the top of the stack when transitioning to AuthScreens after authentication.

    2. ConciergePage lacks an onboarding completion guard:
      In src/pages/ConciergePage.tsx:

      useFocusEffect(
          useCallback(() => {
              if (session && 'authToken' in session) {
                  Navigation.isNavigationReady().then(() => {
                      if (isUnmounted.current || isLoadingReportData === undefined || !!isLoadingReportData) {
                          return;
                      }
      
                      navigateToConciergeChat({
                          conciergeReportID,
                          introSelected,
                          currentAccountID: session.accountID ?? CONST.DEFAULT_NUMBER_ID,
                          isSelfTourViewed,
                          shouldDismissModal: true,
                          checkIfCurrentPageActive: () => !isUnmounted.current,
                      });
                  });
              } else {
                  Navigation.navigate(ROUTES.INBOX);
              }
          }, [session, isLoadingReportData, conciergeReportID, introSelected, isSelfTourViewed]),
      );

      ConciergePage only checks session.authToken and !isLoadingReportData. As soon as OpenApp settles report data (isLoadingReportData turns false), the focus effect immediately calls navigateToConciergeChat({ shouldDismissModal: true }).

    3. Premature redirection bypasses onboarding:
      Calling navigateToConciergeChat with shouldDismissModal: true prematurely navigates to the Concierge chat report and dismisses any modal before the user has completed the onboarding flow (hasCompletedGuidedSetupFlow === false).

    4. Deep link replay in Link.ts is already designed to open after onboarding:
      In src/libs/actions/Link.ts:621-643, the deep link handler already captures initialHasCompletedGuidedSetupFlow === false and defers opening the link until onboarding is finished via setDeepLinkToOpenAfterOnboarding(...), which is subsequently replayed by navigateAfterOnboarding. The premature navigation observed in this bug is caused exclusively by the independent useFocusEffect inside ConciergePage.tsx.


    What changes do you think we should make in order to solve the problem?

    1. Add onboarding completion check to ConciergePage.tsx

    In src/pages/ConciergePage.tsx:

    • Subscribe to ONYXKEYS.NVP_ONBOARDING to derive both isSelfTourViewed and the raw hasCompletedGuidedSetupFlow.
    • Note: We read the raw onboarding?.hasCompletedGuidedSetupFlow directly instead of hasCompletedGuidedSetupFlowSelector, because hasCompletedGuidedSetupFlowSelector returns true for empty objects ({}) or legacy accounts where the property is not yet defined, whereas false is the explicit signal that a user is actively pending onboarding.
    • Return early in useFocusEffect if hasCompletedGuidedSetupFlow === false.
    • Include hasCompletedGuidedSetupFlow in the useCallback dependency array so that if ConciergePage remains focused when onboarding completes, it can cleanly proceed.
    function ConciergePage() {
        const styles = useThemeStyles();
        const {contentHeaderHeightStyle} = useContentHeaderHeight();
        const isUnmounted = useRef(false);
        const [session] = useOnyx(ONYXKEYS.SESSION);
        const [isLoadingReportData = true] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
        const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
        const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
        const [onboarding] = useOnyx(ONYXKEYS.NVP_ONBOARDING);
        const isSelfTourViewed = hasSeenTourSelector(onboarding);
        const hasCompletedGuidedSetupFlow = onboarding?.hasCompletedGuidedSetupFlow;
    
        useFocusEffect(
            useCallback(() => {
                if (session && 'authToken' in session) {
                    Navigation.isNavigationReady().then(() => {
                        if (isUnmounted.current || isLoadingReportData === undefined || !!isLoadingReportData || hasCompletedGuidedSetupFlow === false) {
                            return;
                        }
    
                        navigateToConciergeChat({
                            conciergeReportID,
                            introSelected,
                            currentAccountID: session.accountID ?? CONST.DEFAULT_NUMBER_ID,
                            isSelfTourViewed,
                            shouldDismissModal: true,
                            checkIfCurrentPageActive: () => !isUnmounted.current,
                        });
                    });
                } else {
                    Navigation.navigate(ROUTES.INBOX);
                }
            }, [session, isLoadingReportData, conciergeReportID, introSelected, isSelfTourViewed, hasCompletedGuidedSetupFlow]),
        );

    2. Unit Test Coverage

    Add unit tests in tests/unit/ConciergePageTest.tsx:

    1. Verify that when session.authToken exists, isLoadingReportData is false, and hasCompletedGuidedSetupFlow === false, navigateToConciergeChat is not called.
    2. Verify that when hasCompletedGuidedSetupFlow === true (or undefined for legacy accounts), navigateToConciergeChat is called as expected.
    3. Verify that when hasCompletedGuidedSetupFlow updates from false to true, the focus effect triggers navigation.

    What alternative solutions did you explore? (Optional)

    1. Using hasCompletedGuidedSetupFlowSelector:
      Rejected. As documented in src/selectors/Onboarding.ts and src/libs/actions/Link.ts:543-545, hasCompletedGuidedSetupFlowSelector returns true for empty objects ({}) which can exist transiently on fresh sign-ups before the server responds. Checking hasCompletedGuidedSetupFlow === false on the raw NVP guarantees that pending onboarding is never falsely evaluated as complete.

    2. Intercepting or blocking navigation in OnboardingGuard:
      Rejected. navigateToConciergeChat is a direct action called from components. Intercepting it in router guards increases coupling and risks edge-case regressions across other modals or deeplink handlers. Keeping the guard inside ConciergePage.tsx addresses the root cause directly at the trigger site.

    3. Dropping /concierge route on cold start when logged out:
      Rejected. As established in PR Open a deep link captured before onboarding instead of dropping it #101558, the intended product behavior is to preserve deeplinks opened prior to onboarding so the user reaches their destination immediately after completing setup, rather than discarding the route.

    Contributor details
    Your Expensify account email: bonnhatnguyen0@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~0139ed4098bdc50182

  9. melvin-bot commented on Oct 5, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  10. amar-sheikh commented on Oct 5, 2026

    @amar-sheikh

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Android and iOS, a new user who opens /concierge and then signs up sees the Concierge chat open before the onboarding flow is completed.

    What is the root cause of that problem?

    I agree with the mechanism already laid out on this thread: native preserves [CONCIERGE] in the initial route stack through sign-in (web lazy-loads its screens and drops it), and ConciergePage's focus effect navigates to the Concierge chat as soon as report data has loaded, with no onboarding check at all:

    useFocusEffect(
    useCallback(() => {
    if (session && 'authToken' in session) {
    Navigation.isNavigationReady().then(() => {
    if (isUnmounted.current || isLoadingReportData === undefined || !!isLoadingReportData) {
    return;
    }
    navigateToConciergeChat({
    conciergeReportID,
    introSelected,
    currentUserAccountID: session.accountID ?? CONST.DEFAULT_NUMBER_ID,
    isSelfTourViewed,
    shouldDismissModal: true,
    checkIfCurrentPageActive: () => !isUnmounted.current,
    });
    });
    } else {
    Navigation.navigate(ROUTES.INBOX);
    }
    }, [session, isLoadingReportData, conciergeReportID, introSelected, isSelfTourViewed]),
    );

    I want to flag a gap in the fix already proposed on this thread (checking the raw NVP_ONBOARDING.hasCompletedGuidedSetupFlow === false), because I think it can still race for exactly the account in this report — a brand-new sign-up.

    The existing hasCompletedGuidedSetupFlowSelector has a documented reason for treating an unloaded NVP as "completed" — it literally can't tell "not loaded yet" apart from "already onboarded":

    /**
    * Selector to get the value of hasCompletedGuidedSetupFlow from the Onyx store
    *
    * `true` means the user has completed the NewDot onboarding flow
    * `false` means the user has not completed the NewDot onboarding flow
    *
    * An unloaded NVP answers `true`, so `false` is the only value a caller can trust, because "not loaded yet"
    * and "onboarded" are indistinguishable.
    */
    function hasCompletedGuidedSetupFlowSelector(onboarding: OnyxValue<typeof ONYXKEYS.NVP_ONBOARDING>): boolean {
    // Onboarding is an empty object for old accounts and accounts migrated from OldDot
    if (isEmptyObject(onboarding)) {
    return true;
    }
    if (!isEmptyObject(onboarding) && onboarding?.hasCompletedGuidedSetupFlow === undefined) {
    return true;
    }
    return onboarding?.hasCompletedGuidedSetupFlow;
    }

    Reading the raw field and checking === false only fixes half of that ambiguity. It correctly stops treating "loaded but legacy/empty" as safe, but it does nothing for the case where NVP_ONBOARDING hasn't synced down from the server at all yet — there, hasCompletedGuidedSetupFlow is undefined, not false, so the proposed guard does not block navigation.

    This isn't hypothetical for this bug. The codebase already has a comment acknowledging the server can come back from openApp() with an empty nvp_onboarding even for a user who is genuinely mid-onboarding, which is why a different onboarding-resume path explicitly re-asserts it client-side after the fact:

    /**
    * After required-2FA setup during incomplete guided setup, reload app data then resume onboarding.
    * Re-asserts incomplete onboarding after openApp (server may return empty nvp_onboarding) so AuthScreens
    * mounts ONBOARDING_MODAL_NAVIGATOR, then starts the flow at the resolved resume path.
    */
    async function resumeOnboardingAfterRequired2FASetup(onboardingFlowParams: GetOnboardingInitialPathParamsType) {
    await openApp();
    await Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: false});

    For the exact repro here — a freshly created account, right after sign-up — NVP_ONBOARDING syncing in after isLoadingReportData has already flipped to false is plausible, not an edge case. If that happens, the proposed fix's guard never triggers, and navigateToConciergeChat still fires early.

    The code that actually, correctly decides whether to mount the onboarding modal (AuthScreens.tsx's isOnboardingCompleted === false check) gets its value from useOnboardingFlowRouter, which tracks this exact loading ambiguity separately from the value itself, via the Onyx result's own loading metadata:

    const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP);
    const shouldSuppressPromotionalUI = useShouldSuppressPromotionalUI();
    const [onboardingValues, isOnboardingCompletedMetadata] = useOnyx(ONYXKEYS.NVP_ONBOARDING);
    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
    const [sessionEmail] = useOnyx(ONYXKEYS.SESSION, {selector: emailSelector});
    const isLoggingInAsNewSessionUser = isLoggingInAsNewUser(currentUrl, sessionEmail);
    // A user arriving via a Submit-via-PDF secure access link should land directly on the shared report, not onboarding.
    // The signal must survive the whole session and not depend on navigation timing, so we read the captured deep-link URL
    // (set on cold launch and on warm url events for secure links) alongside the web URL and the active route. getCurrentUrl()
    // is empty on native, and getActiveRoute() serializes the secureKey query param on every platform via getPathFromState.
    const {initialURL} = useInitialURLState();
    const getIsVisitingSecureLink = useCallback(() => hasSecureLinkKey(getCurrentUrl()) || hasSecureLinkKey(Navigation.getActiveRoute()) || hasSecureLinkKey(initialURL), [initialURL]);
    const isVisitingSecureLink = getIsVisitingSecureLink();
    const [tryNewDot, tryNewDotMetadata] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT, {
    selector: tryNewDotOnyxSelector,
    });
    const {isHybridAppOnboardingCompleted, hasBeenAddedToNudgeMigration} = tryNewDot ?? {};
    const isOnboardingLoading = isLoadingOnyxValue(isOnboardingCompletedMetadata, tryNewDotMetadata);

    import type {ResultMetadata} from 'react-native-onyx';
    function isLoadingOnyxValue(...results: ResultMetadata[]): boolean {
    return results.some((result) => result.status === 'loading');
    }

    ConciergePage's proposed fix doesn't use this metadata at all — it only looks at the resolved value.

    What changes do you think we should make in order to solve the problem?

    In ConciergePage, read NVP_ONBOARDING with its metadata (useOnyx(ONYXKEYS.NVP_ONBOARDING) returns [value, metadata]), and block navigation while that key is still loading, not just when it has already resolved to hasCompletedGuidedSetupFlow === false:

    • Block when isLoadingOnyxValue(onboardingMetadata) is true (NVP not synced yet — don't guess).
    • Block when the resolved value's hasCompletedGuidedSetupFlow === false (onboarding confirmed incomplete).
    • Otherwise, proceed as today.

    This mirrors the same loading-vs-value distinction useOnboardingFlowRouter already relies on to correctly gate the onboarding modal itself, instead of re-deriving a second, less careful check inside ConciergePage.

    What alternative solutions did you explore? (Optional)

    Checking only the raw hasCompletedGuidedSetupFlow === false value, as already proposed on this thread, fixes the case hasCompletedGuidedSetupFlowSelector itself warns about (empty/legacy onboarding treated as complete), but not the case where the key hasn't loaded at all yet — which the codebase has already had to work around once, in OnboardingFlow.ts's 2FA-resume path. I'd rather reuse the loading-metadata pattern already proven in useOnboardingFlowRouter than add a second place that can be wrong in the same way.

  11. changed the title [-][$175] Android & iOS - Concierge opens before onboarding is completed[/-] [+][$175] Android - Concierge opens before onboarding is completed[/+] on Oct 5, 2026
  12. kushu7 commented on Oct 5, 2026

    @kushu7
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Android (and iOS), when a user opens staging.new.expensify.com/concierge while logged out (which opens the native app via deep link) and signs up with a new account, the Concierge chat opens immediately and force-dismisses the onboarding flow before the user can complete onboarding.


    What is the root cause of that problem?

    1. Native retains /concierge on the stack: Opening staging.new.expensify.com/concierge triggers the Android App Link intent filter in android/app/src/main/AndroidManifest.xml#L108 (pathPrefix="/concierge"). Unlike Web, Native loads screens synchronously in src/libs/Navigation/AppNavigator/AppNavigator.native.tsx#L25-L30 and preserves SCREENS.CONCIERGE (src/pages/ConciergePage.tsx) at the top of the stack across authentication.

    2. ConciergePage force-dismisses the onboarding modal: src/pages/ConciergePage.tsx#L36-L56 only checks !isLoadingReportData and lacks guards for isLoadingApp or onboarding completion. As soon as report data loads, it calls navigateToConciergeChat({ shouldDismissModal: true }), which force-dismisses the active OnboardingModalNavigator and jumps directly into Concierge chat.

    3. Race condition on fresh sign-ups: Checking only hasCompletedGuidedSetupFlow === false fails because NVP_ONBOARDING is initially undefined before OpenApp resolves. ConciergePage must wait for isLoadingApp === false before evaluating onboarding state.


    What changes do you think we should make in order to solve the problem?

    1. Update src/pages/ConciergePage.tsx:

      • Connect to ONYXKEYS.IS_LOADING_APP to track OpenApp initialization.
      • Connect to ONYXKEYS.NVP_ONBOARDING to read onboarding?.hasCompletedGuidedSetupFlow.
      • In useFocusEffect (src/pages/ConciergePage.tsx#L36-L56), block navigation if:
        • isLoadingApp !== false (app/session data is still loading from the server)
        • isLoadingReportData !== false
        • onboarding?.hasCompletedGuidedSetupFlow === false (user has not completed onboarding)
      • Add isLoadingApp and hasCompletedGuidedSetupFlow to the useCallback dependency array.
    2. Preserve post-onboarding deep link replay:
      Once onboarding completes, navigateAfterOnboarding (src/libs/navigateAfterOnboarding.ts#L120-L122) will automatically replay the parked deep link (deferred via Link.ts / PR #101558) and open Concierge cleanly.

    3. Add unit test coverage in tests/unit/ConciergePageTest.tsx:

      • Verify that navigateToConciergeChat is not called while isLoadingApp is true.
      • Verify that navigateToConciergeChat is not called when hasCompletedGuidedSetupFlow === false.
      • Verify that navigation proceeds once isLoadingApp is false and onboarding is completed (true or legacy accounts).

    What alternative solutions did you explore? (Optional)

    None

  13. 27 remaining items

  14. melvin-bot commented on Oct 26, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  15. melvin-bot commented on Oct 26, 2026

    @melvin-bot

    Payment Summary

    Resolving PRs:

    BugZero Checklist (@mallenexpensify)

    • I have confirmed assignees, roles, and Upwork contracts look correct
    • I have paid out Upwork contracts / manual NewDot requests
    • [BugZero Assignee] I have created a GH issue for creating/updating the regression test once above steps have been agreed upon
  16. eh2077 commented on Oct 29, 2026

    @eh2077
    Contributor

    Contributor+ Checklist:

    • [Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to the comment on the PR: NA. This is a new feature because deeplink only works for existing users and doesn't work for new onboarding users.
      Link to the comment on the Issue: NA

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion: NA

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

    Regression Test Proposal

    Precondition:

    • NA

    Test:

    1. On Android, sign out and open a /concierge app link so it opens in the app.
    2. Sign up with another unused email address, and when the notifications prompt appears, tap "Don't allow".
    3. Verify onboarding stays open instead of being replaced by the Concierge chat.
    4. Finish onboarding and verify the Concierge chat opens.

    Do we agree 👍 or 👎

  17. melvin-bot commented on Oct 29, 2026

    @melvin-bot

    @mallenexpensify Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

  18. mallenexpensify commented on Oct 30, 2026

    @mallenexpensify
    Contributor

    Deploy Blocker #104391 was identified to be related to this PR.

    @eh2077 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.

  19. eh2077 commented on Oct 30, 2026

    @eh2077
    Contributor

    Sorry, I should have commented about it.

    Deploy Blocker #104391 was identified to be related to the PR #103681 that attempted to fix this issue.

    No, this isn't a regression, it's an existing issue, see #104391 (comment)

  20. added and removed on Nov 1, 2026
  21. mallenexpensify commented on Nov 2, 2026

    @mallenexpensify
    Contributor

    Claude posting on behalf of Matt:

    $175 each to @mukhrr (Contributor) and @eh2077 (C+), ie. 100% of the $175 job price. It reproduced on production, so #101558 did not cause it. #103681 fixed it.


    Claude posting on behalf of Matt. PAYRUBRICTEST v1

  22. mallenexpensify commented on Nov 2, 2026

    @mallenexpensify
    Contributor

    Payment Summary

    Contributor: @mukhrr due $175 via NewDot
    Contributor+: @eh2077 due $175 via NewDot

    Thx

  23. flaviadefaria commented on Nov 9, 2026

    @flaviadefaria
    Contributor

    Approved: @mukhrr due $175 via NewDot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions