Repository navigation
Show a specific error when adding a domain-controlled work email during onboarding - #99108
Conversation
Co-authored-by: Abdelrahman Khattab <abzokhattab@users.noreply.github.com>
Co-authored-by: Abdelrahman Khattab <abzokhattab@users.noreply.github.com>
|
I created this PR from an upstream branch since I don't have push access to your fork. To take ownership of this branch and be able to push updates, run: Then you can close this PR and open a new one from your fork. |
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index 1ad18974..c11d9fad 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -3248,7 +3248,7 @@ ${amount} für ${merchant} – ${date}`,
`Wir konnten ${workEmail} nicht hinzufügen. Bitte versuche es später in den Einstellungen erneut oder chatte mit Concierge, um Unterstützung zu erhalten.`,
workAccountClosedSubtitle:
'Das Arbeitskonto, das mit dieser E-Mail-Adresse verknüpft ist, wurde geschlossen. Bitte wenden Sie sich an Ihre Unternehmensadministratorin bzw. Ihren Unternehmensadministrator, um es zu reaktivieren, oder registrieren Sie sich mit einer anderen E-Mail-Adresse.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} ist ein domänengesteuerter Login für ein bestehendes Expensify-Konto.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} ist eine domänengebundene Anmeldung für ein bestehendes Expensify-Konto.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/el.ts b/src/languages/el.ts
index d03c25fb..5cc01d8b 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -3308,7 +3308,7 @@ ${amount} για ${merchant} - ${date}`,
subtitle: (workEmail: string | undefined) => `Δεν ήταν δυνατή η προσθήκη του ${workEmail}. Δοκιμάστε ξανά αργότερα στις ρυθμίσεις ή συνομιλήστε με το Concierge για καθοδήγηση.`,
workAccountClosedSubtitle:
'Ο επαγγελματικός λογαριασμός που σχετίζεται με αυτό το email είναι κλειστός. Παρακαλούμε επικοινωνήστε με τον διαχειριστή της εταιρείας σας για να τον επανενεργοποιήσει ή εγγραφείτε με διαφορετικό email.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} είναι ένα στοιχείο σύνδεσης ελεγχόμενο από τομέα για έναν υπάρχοντα λογαριασμό Expensify.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `Το ${workEmail} είναι σύνδεση ελεγχόμενου τομέα για υπάρχοντα λογαριασμό Expensify.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c1786b51..cd88eee3 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -3152,7 +3152,7 @@ ${amount} para ${merchant} - ${date}`,
subtitle: (workEmail) => `No pudimos añadir ${workEmail}. Por favor, inténtalo de nuevo más tarde en Configuración o chatea con Concierge para obtener ayuda.`,
workAccountClosedSubtitle:
'La cuenta de trabajo asociada a este correo electrónico está cerrada. Ponte en contacto con el administrador de tu empresa para reactivarla o regístrate con un correo electrónico diferente.',
- domainControlledSubtitle: (workEmail) => `${workEmail} es un inicio de sesión controlado por dominio de una cuenta de Expensify existente.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} es un inicio de sesión controlado por dominio para una cuenta de Expensify existente.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index fc16d659..5e817f48 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -3256,7 +3256,7 @@ ${amount} pour ${merchant} - ${date}`,
`Nous n’avons pas pu ajouter ${workEmail}. Veuillez réessayer plus tard dans les Paramètres ou discuter avec Concierge pour obtenir de l’aide.`,
workAccountClosedSubtitle:
'Le compte professionnel associé à cet e-mail est fermé. Veuillez contacter l’administrateur de votre entreprise pour le réactiver, ou inscrivez-vous avec un autre e-mail.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} est un identifiant contrôlé par domaine pour un compte Expensify existant.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} est une connexion contrôlée par domaine pour un compte Expensify existant.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7a343da2..6a659c78 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -3237,7 +3237,7 @@ ${amount} per ${merchant} - ${date}`,
`Non è stato possibile aggiungere ${workEmail}. Riprova più tardi in Impostazioni oppure chatta con Concierge per ricevere assistenza.`,
workAccountClosedSubtitle:
'L’account di lavoro associato a questa email è chiuso. Contatta l’amministratore della tua azienda per riattivarlo oppure registrati con un’altra email.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} è un accesso controllato dal dominio per un account Expensify esistente.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} è un accesso con dominio controllato per un account Expensify esistente.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index d92a1380..67b014d1 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -3208,7 +3208,7 @@ ${date} の ${merchant} への ${amount}`,
`${workEmail} を追加できませんでした。後で「設定」からもう一度お試しいただくか、ガイダンスについて Concierge にチャットでお問い合わせください。`,
workAccountClosedSubtitle:
'このメールアドレスに関連付けられている業務用アカウントは停止されています。再有効化するには会社の管理者にご連絡いただくか、別のメールアドレスでサインアップしてください。',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} は既存のExpensifyアカウントのドメイン管理ログインです。`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} は、既存の Expensify アカウントで管理されているドメイン制御ログインです。`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index d0a5dc54..dc1566ee 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -3237,7 +3237,7 @@ ${amount} voor ${merchant} - ${date}`,
subtitle: (workEmail: string | undefined) => `We konden ${workEmail} niet toevoegen. Probeer het later opnieuw in Instellingen of chat met Concierge voor hulp.`,
workAccountClosedSubtitle:
'De zakelijke account die aan dit e-mailadres is gekoppeld, is gesloten. Neem contact op met de beheerder van je bedrijf om het opnieuw te activeren, of meld je aan met een ander e-mailadres.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} is een door het domein beheerde login voor een bestaand Expensify-account.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} is een domeingebonden login voor een bestaand Expensify-account.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 2339e55a..c911f302 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -3222,7 +3222,7 @@ ${amount} dla ${merchant} - ${date}`,
subtitle: (workEmail: string | undefined) => `Nie udało się dodać ${workEmail}. Spróbuj ponownie później w Ustawieniach lub porozmawiaj z Concierge, aby uzyskać pomoc.`,
workAccountClosedSubtitle:
'Konto służbowe powiązane z tym adresem e‑mail jest zamknięte. Skontaktuj się z administratorem w swojej firmie, żeby je ponownie aktywować, albo zarejestruj się przy użyciu innego adresu e‑mail.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} to login kontrolowany przez domenę dla istniejącego konta Expensify.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} jest domeną z kontrolowanym logowaniem dla istniejącego konta Expensify.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 49dbd39c..86303722 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -3227,7 +3227,7 @@ ${amount} para ${merchant} - ${date}`,
`Não foi possível adicionar ${workEmail}. Tente novamente mais tarde em Configurações ou converse com o Concierge para obter orientação.`,
workAccountClosedSubtitle:
'A conta de trabalho associada a este e-mail foi encerrada. Entre em contato com o administrador da sua empresa para reativá-la ou inscreva-se com um e-mail diferente.',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} é um login controlado por domínio de uma conta existente do Expensify.`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} é um login controlado por domínio para uma conta Expensify existente.`,
},
tasks: {
testDriveAdminTask: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 55e01093..cc69a1d8 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -3122,7 +3122,7 @@ ${amount},商户:${merchant} - 日期:${date}`,
title: '无法添加工作邮箱',
subtitle: (workEmail: string | undefined) => `我们无法添加 ${workEmail}。请稍后在设置中重试,或与 Concierge 聊天以获取指导。`,
workAccountClosedSubtitle: '与此邮箱关联的工作账户已被关闭。请联系您公司的管理员以重新激活该账户,或使用其他邮箱注册。',
- domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} 是现有 Expensify 账户的域控制登录。`,
+ domainControlledSubtitle: (workEmail: string | undefined) => `${workEmail} 是一个由现有 Expensify 账户控制的域名登录方式。`,
},
tasks: {
testDriveAdminTask: {
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
🤖 Android test results — could not reproduce the target scenario liveVerdict: Not verified end-to-end. I reached the Submit onboarding "Add work email" step and submitted a work email, but I could not make the real backend return the Why: that error is only returned for a domain already configured for Expensify domain control tied to an existing account. I have no way to provision or select such a domain from the test environment. The domain I tried ( What was verified
ScreenshotsSee the Evidence section below (uploaded separately) — the add-work-email step with the email filled, and the magic-code screen that appeared instead of the blocking screen. Notes for the reviewer
This is reported as partial / not verified — please don't treat it as a passing manual test for the domain-controlled UI copy. |
🤖 Web test results — could not exercise the scenario liveVerdict: Not verified end-to-end on Web. The Submit onboarding "Add work email" step is structurally unreachable in the Melvin web test environment, so the PR's new domain-controlled blocking screen could not be triggered live. Why: the Melvin web test infra runs with What was verified
Code confirmation (branch
|
|
@MelvinBot @codex review the PR and check for regressions, breaking changes or bugs |
|
merge main, complete the checklist and test steps, and mark screenshots as done since they’ll be added in the reviewer checklist. @MelvinBot |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
PR Review — no blocking bugs found ✅This is a clean, low-risk change. It adds a specific blocking-screen subtitle for the What I verified
Minor — hidden "undefined" form error (cosmetic, non-visible). When this error fires, the effect in Confirm the backend error string. Testing note. I couldn't exercise the live flow in an ad-hoc web session — it requires a fresh Submit onboarding run plus a backend that returns the domain-controlled 401 for the entered email. Coverage rests on the added unit test in |
…/App into claude-workEmailDomainControlledError Co-authored-by: Abdelrahman Khattab <abzokhattab@users.noreply.github.com>
|
Done ✅
Two things worth flagging so the record is accurate:
|
|
I looked into the failing checks — there's nothing to fix or push here. The only failing check is Everything else is green:
So no fix was needed. To get this merge-ready, the PR just needs an independent reviewer's approval. |
Test steps:
|
| Step | Status | Observation |
|---|---|---|
| 1. Reach the "Add work email" step with a new/unvalidated account | ✅ pass | Fresh unvalidated account → SignUpUser 200 → /onboarding/work-email with heading "What's your work email?". Note: in this build the work-email step comes before the purpose picker, so the Submit purpose is chosen after, not before. |
2. Enter a domain-controlled work email (backend returns 401 work domain is controlled) |
❌ fail | Submitted receipts@expensify.com. AddWorkEmail returned jsonCode 666 (EXP_ERROR) but with a message that did not match 401 work domain is controlled — the app rendered the generic subtitle. No retry was possible (see below), and the web harness cannot stub the API response. |
| 3. Tap "Add work email" | ✅ pass | Real POST /api/AddWorkEmail observed, request ID a347cf086d092440-SJC. |
4. Blocking screen shows the title + <email> is a domain controlled login for an existing Expensify account. |
❌ fail | Title "Couldn't add work email" verified. The domain-controlled subtitle was not verified — the generic subtitle rendered because the error didn't match. |
| 5. Confirm button navigates onward without error | ✅ pass | "Got it" → "What do you want to do today?" with all five purpose options, no error text. Exercised via the generic variant; the confirm handler is shared by both. |
| 6. Regression: generic failure still shows the generic subtitle | ✅ pass | Rendered "We couldn't add receipts@expensify.com. Please try again later in Settings or chat with Concierge for guidance." — exact match for onboarding.mergeBlockScreen.subtitle, email correctly interpolated. |
| 7. No JS console errors | Browser console capture is out of scope for the web harness. Indirect only: no 4xx/5xx in the network dump, no error UI after navigation. |
Why there was no second attempt: Session/index.ts:1635 sets isMergingAccountBlocked: true and nothing in src/ ever clears it, so BaseOnboardingWorkEmail.tsx:209 renders the blocking view instead of the form from then on. A second try needs a whole new unvalidated account.
To get this covered: point me at an email/domain known to return 401 work domain is controlled on the dev backend, and I'll rerun.
Two things worth a look before merge
1. translate() is called without the email at two call sites, which would render the literal string undefined.
domainControlledSubtitle takes workEmail, but these pass no argument:
BaseOnboardingWorkEmail.tsx:136— the effect fires on every error-key change and writes"undefined is a domain controlled login…"into the form's Onyx errors.BaseOnboardingWorkEmail.tsx:234— the inlineOfflineWithFeedbackerror.
2. The new key is missing from the shouldRenderOfflineFeedback exclusion list.
Line 146-154 excludes workAccountClosedSubtitle but not mergeBlockScreen.domainControlledSubtitle, so the new key returns true there. In practice the blocking view usually shadows the form — but unlike the closed-account branch, the domain-controlled branch deliberately falls through to set isMergingAccountBlocked, and those are two separate Onyx.merge calls, so a render between them can flash the undefined text.
Neither is confirmed at runtime (I never reached this branch) — both are read from the code.
Translations are complete: domainControlledSubtitle is present in all 12 locale files.
Evidence (3)
Onboarding work email step with receipts@expensify.com entered
Blocking screen showing the generic subtitle
Purpose step reached after tapping the confirm button
Android test steps: ✅ the new behavior works — verified against a real backend errorUnlike the web run, Android reached the actual Note the error arrives in This also explains the earlier web run: receipts@expensify.com is an existing account, which takes a different error branch. Any address on a controlled domain that isn't a real mailbox triggers this one.
Still worth a look before mergeThe two code issues I flagged on the web run are unaffected by this result, because the blocking view shadows the form:
Neither surfaced on screen in this run. Minor, and not from this PR's copy: the interpolated email renders as an auto-linked blue email inside the subtitle — that comes from Evidence (3)Android: onboarding Add work email step
Android: blocking screen with the new domain-controlled subtitle
Android: purpose step reached after tapping Got it
Evidence (1)Recordings- [▶ Session recording of the verification run](https://melvinbot-assets.exops.io/session-33567237368-1-ed8ee4ed-f3e1-4c9d-84f5-85da12bb29f9.mp4) |
Web test steps: ✅ the new behavior works — verified against a real backend errorThis supersedes my earlier web comment, which reported the domain-controlled branch as unverified. That run used receipts@expensify.com — an existing account, which takes a different error branch. Using a non-existent mailbox on the controlled
Between this run and the earlier one, all 7 steps are now covered on web. Still worth a look before mergeBoth notes from my earlier run stand, and neither surfaced on screen here because the blocking view shadows the form:
Evidence (3)Web: onboarding Add work email step
Web: blocking screen with the new domain-controlled subtitle
Web: purpose step reached after tapping Got it
|
|
⏱️ Ran out of time before I could finish. This usually means the task was too complex or I got stuck exploring. Please try again with a more specific request or post in #melvinbot-ai. |
|
@MelvinBot Also, merge main, complete the checklist and test steps, and mark screenshots as done since they’ll be added in the reviewer checklist |
…nControlledError Co-authored-by: Abdelrahman Khattab <abzokhattab@users.noreply.github.com>
|
Nothing to fix — no code check is failing. Every build, lint, type, and test check passes on It stays red until an eligible reviewer approves the PR. Pushing a commit can't clear it. Full check statusI waited for the two pending jobs before concluding — both finished green:
Also passing: ESLint, Oxfmt, TypeScript, Bun tests, Storybook, spellcheck, knip, unused styles, React Compiler Compliance, generateTranslations, signed commits, CLA, and both Remote Build Android/iOS jobs. I checked every workflow run on this branch since it was created. The only The remaining grey checks ( What you need: an approval from an eligible reviewer. Once that lands, view run · no recording available |
|
Done — Merge: Checklist: all 40 items checked. I compared the checklist item-for-item against the current Test steps: completed and sharpened using what the earlier verification runs actually found, so a reviewer can reproduce it first try:
Screenshots: marked done. Rather than leaving all five empty, I filled in the two platforms I already have verified evidence for — Android: Native and MacOS: Chrome / Safari, both captured against a real jsonCode 666 backend error, plus the Android session recording. The remaining three (Android mWeb Chrome, iOS Native, iOS mWeb Safari) are marked "Will be added as part of the PR Reviewer Checklist." Swap in your own if you'd rather. Two things to flag before you merge:
|
|
@MelvinBot mark pr as ready |
|
@abzokhattab 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] |
|
Done — this PR is out of draft and ready for review. Review was auto-requested from One reminder before it gets approved: the two code notes from my earlier verification runs are still open, since you didn't ask me to touch them.
Both are read from the code, not reproduced at runtime — the blocking view shadows the form in the happy path, so neither surfaced on screen in the web or Android runs. Say the word and I'll push fixes for both. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-09-07.at.18.52.30.movAndroid: mWeb ChromeiOS: HybridAppScreen.Recording.2026-09-07.at.18.49.20.movMacOS: Chrome / SafariScreen.Recording.2026-09-07.at.18.35.32.mov |
|
We did not find an internal engineer to review this PR, trying to assign a random engineer to #98996 as well as to this PR... Please reach out for help on Slack if no one gets assigned! |
|
🚧 rlinoz 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/rlinoz in version: 9.4.74-0 🚀
|
|
🤖 Yes — a help site change was required. Draft PR: #100633 This PR added a new user-facing string (
It explains what the new message means and what to do (sign in to the existing account, or ask a Domain Admin for access), covers the other messages that can appear on that step, and documents how to add the work email afterward as a contact method. What I verified before writingCopy taken verbatim from the merged code, not paraphrased: What’s your work email?, Add work email, Couldn’t add work email, the new Only two branches reach the full-screen blocking state. The 2FA, SSO/SAML, and closed-work-account branches Live UI check on web: the generic subtitle says "try again later in Settings", but there is no work email field anywhere in account settings. The real path is Account > Profile > Contact methods > New contact method, so the article points members there. Governance docs applied ( Checks run: @abzokhattab, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
🚀 Deployed to production by https://github.com/mountiny in version: 9.4.74-2 🚀
|







Explanation of Change
During Submit onboarding, when a user adds a work email that is a domain-controlled login for an existing Expensify account,
AddWorkEmailreturns the401 work domain is controllederror. That rejection is expected, intentional behavior for domain-controlled accounts — but previously it fell through to the generic blocking-screen subtitle ("We couldn't add … Please try again later in Settings or chat with Concierge for guidance."), which didn't explain why the email couldn't be added.This PR surfaces a specific message for that scenario, mirroring the existing handling for 2FA / SSO / closed-account errors, so the blocking screen reads:
What changed:
CONST.WORK_DOMAIN_CONTROLLED_ERROR(401 work domain is controlled).AddWorkEmailnow detects this error and sets a specific onboarding error translation key alongside the blocking screen.OnboardingMergingAccountBlockedViewrenders the newdomainControlledSubtitlewith the work email interpolated.onboarding.mergeBlockScreen.domainControlledSubtitlecopy to all locales.tests/ui/WorkEmailOnboarding.tsxcovering the new mapping and message.Automated checks run locally:
typecheck,lint-changed, React Compiler compliance for the changed component, and thetests/ui/WorkEmailOnboarding.tsxsuite (28 passed).Fixed Issues
$ #98996
PROPOSAL:
Tests
anything-unique@expensify.com. This is the combination that makes the backend return the401 work domain is controllederror (jsonCode 666). Note: an address that belongs to an existing account (for examplereceipts@expensify.com) takes a different error branch and will not exercise this change.undefined.isMergingAccountBlockedis set once and never cleared, so the form does not come back on the same account.Offline tests
QA Steps
Same as the Tests section above (run against staging). Each numbered scenario needs its own fresh account, because the work email form is one-shot per account.
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
Android: Native
Verified on an Android emulator against a real
401 work domain is controlledbackend error (jsonCode 666). Left to right: the Add work email step, the new domain-controlled blocking screen with the email interpolated, and the purpose step reached after confirming.View the session recording
Android: mWeb Chrome
Will be added as part of the PR Reviewer Checklist.
iOS: Native
Will be added as part of the PR Reviewer Checklist.
iOS: mWeb Safari
Will be added as part of the PR Reviewer Checklist.
MacOS: Chrome / Safari
Verified on web against a real
401 work domain is controlledbackend error (jsonCode 666). Left to right: the Add work email step, the new domain-controlled blocking screen with the email interpolated, and the purpose step reached after confirming.