Skip to content

Show Rain SMS requirement before card KYC - #3185

Closed
innolope-dev wants to merge 5 commits into
devfrom
innolope/rain-kyc-sms-requirement
Closed

innolope-dev wants to merge 5 commits into
devfrom
innolope/rain-kyc-sms-requirement

Conversation

@innolope-dev

@innolope-dev innolope-dev commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • pause every Rain card KYC entry path on the requirements drawer before opening Sumsub
  • show Rain-specific tax ID, SMS, email, and questionnaire requirements for the normal approved-user path
  • reuse retained Sumsub identity documents; add only a still-missing selfie for verified users, while new KYC lists ID + selfie
  • describe standard KYC as taking a few minutes rather than promising an explicit two-minute duration
  • leave Bridge, Manteca, hosted, and card applications that do not require KYC unchanged
  • localize the new requirements in English, Latin American Spanish, Argentine Spanish, and Brazilian Portuguese

Product dependency

  • Companion product/content correction: peanutprotocol/mono#187
  • The UI PR should not merge before that product review lands; it corrects stale no-second-pass and numeric KYC timing claims across canonical sources and generated content.

Validation

  • focused Jest: 13/13
  • targeted ESLint
  • full typecheck
  • Prettier check
  • locale JSON parse
  • exact-head CI success

@coderabbitai

coderabbitai Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 13f439de-8812-49c6-8768-a23557119848

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vercel

vercel Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
peanut-wallet Ready Ready Preview Sep 15, 2026 2:18pm UTC

Request Review

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 8252.92 → 8254.82 (+1.9)
Findings: +1 net (+15 new, -14 resolved)

🆕 New findings (15)

  • critical complexity — src/features/card/useCardFlow.ts — CC 84, MI 52.53, SLOC 428
  • high complexity — src/features/card/CardPage.tsx — CC 36, MI 60.75, SLOC 136
  • medium high-mdd — src/features/card/useCardFlow.ts:25 — useCardFlow: MDD 110.1 (uses across many lines from declarations)
  • medium high-dlt — src/features/card/useCardFlow.ts:25 — useCardFlow: DLT 54 (calls 54 distinct functions — high context load)
  • medium high-mdd — src/features/card/CardPage.tsx:18 — CardPage: MDD 41.4 (uses across many lines from declarations)
  • medium high-mdd — src/components/Kyc/KycPrepChecklist.tsx:26 — KycPrepChecklist: MDD 32.6 (uses across many lines from declarations)
  • medium high-mdd — src/components/IdentityVerification/UnlockMethodModal.tsx:32 — UnlockMethodModal: MDD 29.2 (uses across many lines from declarations)
  • medium high-mdd — src/features/card/CardPage.tsx:85 — renderState: MDD 25.8 (uses across many lines from declarations)
  • medium method-complexity — src/features/card/CardPage.tsx:85 — CC 19 SLOC 46
  • medium complexity — src/components/Kyc/KycPrepChecklist.tsx — CC 10, MI 63.15, SLOC 22
  • low high-dlt — src/features/card/CardPage.tsx:18 — CardPage: DLT 18 (calls 18 distinct functions — high context load)
  • low high-mdd — src/features/card/useCardFlow.ts:192 — : MDD 16.7 (uses across many lines from declarations)
  • low high-mdd — src/features/card/useCardFlow.ts:367 — : MDD 16.2 (uses across many lines from declarations)
  • low structural-dup — components/AddMoney/components/OnrampConfirmationModal.tsx:25 — 14 duplicate lines / 62 tokens with components/IdentityVerification/UnlockMethodModal.tsx:43
  • low missing-return-type — src/features/card/CardPage.tsx:18 — CardPage: exported fn missing return type annotation

✅ Resolved (14)

  • src/features/card/useCardFlow.ts — CC 79, MI 52.25, SLOC 404
  • src/features/card/CardPage.tsx — CC 36, MI 61.23, SLOC 131
  • src/features/card/useCardFlow.ts:25 — useCardFlow: MDD 106.5 (uses across many lines from declarations)
  • src/features/card/useCardFlow.ts:25 — useCardFlow: DLT 51 (calls 51 distinct functions — high context load)
  • src/features/card/CardPage.tsx:17 — CardPage: MDD 30.8 (uses across many lines from declarations)
  • src/components/IdentityVerification/UnlockMethodModal.tsx:28 — UnlockMethodModal: MDD 29.2 (uses across many lines from declarations)
  • src/features/card/CardPage.tsx:80 — renderState: MDD 25.8 (uses across many lines from declarations)
  • src/components/Kyc/KycPrepChecklist.tsx:25 — KycPrepChecklist: MDD 25.1 (uses across many lines from declarations)
  • src/features/card/CardPage.tsx:80 — CC 19 SLOC 46
  • src/features/card/CardPage.tsx:17 — CardPage: DLT 18 (calls 18 distinct functions — high context load)
  • src/features/card/useCardFlow.ts:352 — : MDD 16.2 (uses across many lines from declarations)
  • components/AddMoney/components/OnrampConfirmationModal.tsx:25 — 14 duplicate lines / 62 tokens with components/IdentityVerification/UnlockMethodModal.tsx:37
  • src/features/card/useCardFlow.ts:182 — : MDD 14.3 (uses across many lines from declarations)
  • src/features/card/CardPage.tsx:17 — CardPage: exported fn missing return type annotation

📈 Painscore deltas (top movers)

File Before After Δ
src/components/Kyc/KycPrepChecklist.tsx 6.7 7.6 +0.8
src/features/card/useCardFlow.ts 10.9 11.4 +0.6

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • ✅ unit: 7534 ran, 0 failed, 0 skipped, 2.7m

📊 Coverage (unit)

metric %
statements 78.3%
branches 65.3%
functions 72.2%
lines 79.3%
⏱ 10 slowest test cases
time test
🐢 9.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Network failure keeps loading while retries remain, then shows the generic error
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_SOURCE_OVER_MONTHLY_CAP fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › User KYC not approved fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › a refused idempotency key tells the user to scan again, not to contact support
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_MERCHANT_RECENT_REFUND fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_USER_NOT_PROVISIONED fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_MERCHANT_VOLUME_NEAR_CAP fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › routes the KYC rejection on its wire code, and does not retry it
3.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Scan that recovers on the retry lands on the payment screen, not an error
3.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Going offline blames the connection, and reconnecting clears it for the recovered scan
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@chip-peanut-bot chip-peanut-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip review — no blocking findings — this is not an approval

The Rain checklist and incomplete-response gate are coherent, but the main-KYC response still bypasses the new SMS disclosure.

Findings

  • MAJOR · src/features/card/useCardFlow.ts:54 · Gate the main-KYC response through the Rain prep drawer
    A card-access user with no approved base KYC receives main-kyc-required; advanceFromApplyResponse still puts that token straight into sumsubToken, so the WebSDK opens without setting pendingSumsubToken. The backend mints this token for the same Rain verification level whose steps include phone verification, making this a reachable cohort that encounters the SMS challenge without the new warning. Stage main-kyc-required through the prep token as well, and cover that response in the hook test.

  • MAJOR · src/features/card/CardPage.tsx:254 · [claude-opus] Card prep uses standard copy, understating the Rain level's steps and its duration
    CardPage renders the prep with path="standard", so the card user now sees the copy written for the 3-step general level: intro "Get these ready now, so you are not hunting for them halfway through", items ID + selfie + SMS, and kyc.prep.howLong.standard = "Under 2 minutes for most people" (src/i18n/app/messages/en.json:2980).

Product truth disagrees on both counts, and the code is the wrong side:

  • Steps: peanut-api-ts/src/routes/rain/apply.ts (~line 658) documents VERIFICATION_LEVELS.rain as "document collection, selfie, applicant data (incl. editable phone + TIN), phone verification, email verification, and the rain-card-extraInformation questionnaire". /home/chip/mono/product/feedback/problems/card-onboarding-friction.md (2026-09-09 PostHog, nita creator cohort) states the same thing user-side: "the card Sumsub level has 6 steps (ID, selfie, personal data, SMS, email code, questionnaire) vs 3 on the standard level". product/card.md § KYC lists tin among the fields shared with Rain, and the friction doc's 2026-05-01 entry is a user being asked to resubmit his TIN during card KYC. The checklist exists precisely to stop users hunting mid-flow, yet the tax ID — the one item a user may have to go and find — is omitted, as is the email code.
  • Duration: the same PostHog entry measures "approved users take ~8 min" for this level. "Under 2 minutes for most people" is roughly 4x off for the path it is now shown on.

This PR is what puts that copy in front of card applicants for the first time (the modal is newly mounted in CardPage), so the disagreement ships with it.

Fix: give the Rain card path its own requirements and duration rather than borrowing standard — either add taxId (with copy that is not Manteca/LATAM-specific, since the existing items.taxId.body names CPF/CUIT only) and an email-code item to the provider === 'rain' add-on in KycPrepChecklist, and a howLong.rain string reflecting the measured ~8 minutes; or introduce a fourth path for the Rain level. If the 6-step figure is stale and the level has since been trimmed, the product doc is what needs correcting — but one of the two has to move.

Checked clean

  • Confirmed the detached worktree HEAD, merge base, trusted author, base ref, and exact base/head SHAs match the supplied target.
  • Traced incomplete, main-kyc-required, country-confirmation, terms, refresh, resume, close, and completion paths across the card hook and modal rendering.
  • Checked the sibling API contract: both incomplete and main-kyc-required tokens target the Rain verification level, which includes phone verification.
  • Reviewed locale keys and inheritance for English, Latin American Spanish, Argentine Spanish, and Brazilian Portuguese.
  • Exact-head substantive CI is green, including unit, typecheck, ESLint, format, native-export, and analyze; advisory visual captures and preview deployment remain in progress.
  • Focused local Jest execution was unavailable because the detached worktree has no node_modules; exact-head unit CI passed.

Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.

Third opinion by claude-opus: 1 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Exact head: a361fc7e997f · Context: repo, sibling-api, ci · Took 9m

Comment thread src/features/card/useCardFlow.ts
@innolope-dev

Copy link
Copy Markdown
Collaborator Author

Addressed both Chip findings at exact head 35f2eeb: (1) main-kyc-required now passes through the Rain prep drawer before Sumsub opens; (2) Rain prep now lists the full provider-specific set—ID, selfie, generic tax ID, SMS, email code, and regulatory questions—and uses the measured ~8-minute duration instead of standard KYC copy. All four app locales are covered, including the es-AR delta fallback. Validation: 10 focused tests, 246 i18n tests, targeted ESLint, Prettier, and pnpm typecheck all passed.

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

🖼 Visual diff — 2 screens moved

4 of 94 shots changed · 90 identical · baseline 5ed9303 → head 2e3b411

worst % screen widths
10.74% avatar-picker 320, 430
3.43% guest-invite 320, 430

job summary · before/after/diff images — artifact

Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data.

@chip-peanut-bot chip-peanut-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip review — no blocking findings — this is not an approval

Both prior Rain KYC-prep defects are fixed; no new defects found.

Findings

  • MAJOR · src/i18n/app/messages/en.json:2991 · [claude-opus] Rain card prep contradicts product truth: "no second pass, under 2 minutes"
    This PR makes the app tell card applicants, before KYC, that the card check needs a tax ID, an SMS code, an email code and a questionnaire, and takes "About 8 minutes for most people" (en.json kyc.prep.howLong.rain, plus the rainTaxId/sms/emailCode items, wired in at CardPage.tsx:249-256 with provider="rain").

Product truth says the opposite, in three places:

  • /home/chip/mono/product/kyc.md:31 — "The Peanut Card reuses the existing Sumsub verification (shared with Rain) — no card-specific verification flow." Also kyc.md:184 and product/card.md:191 ("users do not complete a second pass").
  • /home/chip/mono/product/kyc.md:77 — average_time: "Under 2 minutes for most users"; kyc.md:150 repeats it.
  • The generated customer-facing page already published from that truth: /home/chip/mono/content/help/peanut-card/en.md:74 — "Do I need to verify my identity again to get the card? No. If your Peanut account is already verified, the card uses the same verification and there is no second pass."

The drawer fires precisely on the case product denies: an incomplete response for an already-KYC'd user, i.e. a second, card-specific pass.

The code is the side that is right, not the docs. peanut-api-ts has a distinct rain-requirements level (src/kyc/level-registry.ts:28) with its own card questionnaire (rain-card-extraInformation, src/sumsub/consts.ts), and product/providers/rain.md lists tin, email, phone among the fields Rain requires — so a card-specific level with extra challenges genuinely exists. product/kyc.md and product/card.md are stale, and the help page generated from them will now tell users the opposite of what the app shows.

Fix: update product/kyc.md (kyc_scope.note, verification.average_time, the Peanut Card section) and product/card.md § KYC to describe the Rain card-application level and its duration, then regenerate content/help/peanut-card and content/help/verification. Separately, record where "about 8 minutes" comes from — nothing in product/ or either repo documents a duration for this level, so the new wait-time promise currently has no source of truth behind it.

  • MINOR · src/features/card/useCardFlow.ts:194 · [claude-opus] Full Rain 8-minute prep is shown when only one doc step is missing
    advanceFromApplyResponse now stages every main-kyc-required token behind the same Rain prep drawer (useCardFlow.ts:194-196). That branch has two very different causes in peanut-api-ts: no APPROVED Sumsub row at all (src/routes/rain/apply.ts:572, the whole level really is ahead of the user), and an approved user missing a single doc such as SELFIE (src/routes/rain/apply.ts:651). In the second case the SDK asks only for that one step — the code's own comment says so ("Sumsub itself still asks only for the missing step once the user continues"), as does apply.ts:585-590.

A user who needs a 30-second selfie re-take is therefore told to have a tax ID ready, that they will receive SMS and email codes, and that this will take "About 8 minutes". That is a wait-time overstatement on the most common re-entry path, and the kind of thing that makes people abandon the drawer instead of tapping through.

The response already carries the signal: the no-KYC branch sends the full RAIN_REQUIRED_DOC_TYPES, the doc-gap branch a subset. Gate the provider="rain" copy (or at least the duration line) on the full-level case and fall back to the base standard prep when missingDocTypes is a narrow subset. The P1 gating stays intact either way — this is about which copy the drawer shows, not whether it appears.

Checked clean

  • All incomplete and main-kyc-required card-apply responses now stage the Sumsub token behind the Rain prep drawer; refresh and reload-resume stay inside an already-started SDK session.
  • The Rain drawer resolves ID, selfie, tax-ID, SMS, email-code, and questionnaire requirements plus the longer Rain duration in all four app locales; non-Rain callers retain their existing path copy.
  • The exact-head unit, typecheck, format, ESLint, native-export, screen, design-system lint, and backend-baseline checks passed. The report job failed only in its GitHub-comment step with an unexpected JSON parse error, so ci-success is red even though this PR changes no workflow files.
  • The Product Lexicon, Rain compliance reference, card product sources, and paired API response/control-flow contract were checked.

Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.

Third opinion by claude-opus: 2 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Exact head: 35f2eeb4363d · Context: repo, product · Took 14m

@innolope-dev

Copy link
Copy Markdown
Collaborator Author

Addressed both new Chip findings. At exact UI head 0422097, an already-verified user sent back for one missing main-KYC document now gets the short standard prep; users who still need the full Rain level keep the complete Rain checklist and ~8-minute estimate. The live backend has RAIN_REQUIRED_DOC_TYPES = [SELFIE], so missingDocTypes cannot distinguish the two cohorts; the UI uses the provider-neutral identityVerification.status signal that mirrors the backend approval gate. Added regression coverage. Validation: 11 focused tests, targeted ESLint and Prettier, and pnpm typecheck passed.

The stale product and help claims are corrected at exact mono head 7aac3ad8c8d963e1f5f584069b10f9ef6ecd087d in peanutprotocol/mono#187. That PR documents the Rain-specific level, records the ~8-minute PostHog source, and refreshes every existing Peanut Card and verification help locale. Markdown diff checks pass.

@chip-peanut-bot chip-peanut-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip review — no blocking findings — this is not an approval

One supplied major finding remains: the Rain prep still presents an eight-minute full verification to already verified users, contradicting the documented shared-KYC flow. P1, P3, and P4 are fixed.

Findings

  • MAJOR · src/i18n/app/messages/en.json:2991 · Rain prep still promises a second full verification
    Every incomplete response is reached only after the API has selected an APPROVED Sumsub identity and confirmed its required ID/selfie documents, yet this path sets provider=rain, lists those documents again, and shows this eight-minute estimate. The canonical card contract says the existing Sumsub KYC is shared with Rain and users do not complete a second pass. This makes a verified user expect substantially more work than the SDK should require. Keep retained ID/selfie out of the Rain add-on and estimate only the additional phone, email, tax-ID, and questionnaire steps, or update the authoritative product contract first if a full second pass is now intended.

  • MAJOR · src/i18n/app/messages/en.json:2991 · [claude-opus] Product truth still promises "no second pass" for the card
    This PR makes the app tell card applicants they need a phone SMS code, an email code, a tax ID and a questionnaire, and that it takes about 8 minutes. That is correct against the backend: /rain/apply step 5 moves every applicant — including ones with an APPROVED Sumsub row and all docs collected — to VERIFICATION_LEVELS.rain, and returns status:'incomplete' with a token until that level is GREEN (peanut-api-ts/src/routes/rain/apply.ts:659-746; the comment there lists the level's steps as "document collection, selfie, applicant data (incl. editable phone + TIN), phone verification, email verification, and the rain-card-extraInformation questionnaire").

Product truth says the opposite in four places, so the docs are the wrong side and must be corrected:

  • /home/chip/mono/product/card.md:191 — "users do not complete a second pass"
  • /home/chip/mono/product/kyc.md:184 and :164 — "already-verified users do not complete a second pass"
  • /home/chip/mono/product/providers/rain.md — "We do not collect KYC twice"
  • and it has already reached customers: /home/chip/mono/content/help/peanut-card/en.md:74 — "If your Peanut account is already verified, the card uses the same verification and there is no second pass."

The published help answer will be flatly contradicted by the drawer this PR ships (6 items, ~8 minutes) for exactly the users it addresses. Support will be answering "the help page said no second verification" tickets on day one.

Fix: no code change here. Update card.md / kyc.md / providers/rain.md to say token sharing avoids re-uploading documents but the card still requires a Rain requirements pass (phone OTP, email OTP, TIN, questionnaire), regenerate the help page through the update-content path, and record where the "about 8 minutes" figure comes from so the docs and the string share one source. Rain's 14-day marketing-review window on public card copy (providers/rain.md) means this should start now, not after merge.

  • MINOR · src/features/card/useCardFlow.ts:199 · [claude-opus] Verified user re-entering for a missing doc is promised "under 2 minutes" but lands in the 8-minute Rain level
    On main-kyc-required the hook now shows the short standard prep (ID + selfie, "Under 2 minutes for most people") whenever user.identityVerification.status === 'verified'. But the token behind that drawer is minted at VERIFICATION_LEVELS.rain, not at the user's old level: peanut-api-ts/src/routes/rain/apply.ts mints generateAccessToken(userId, mainLevel) with mainLevel = VERIFICATION_LEVELS.rain in the missing-docs branch, and in the dominant case for that branch — the "Imported from Manteca" applicant with no SELFIE step at all — it first calls moveToLevel(applicantId, rain), which re-applies the level's current step config and therefore adds the phone-verification, email-verification, TIN and questionnaire steps to that applicant. The WebSDK then presents every incomplete step, so the user who was just told "ID and selfie, under 2 minutes" is asked for an SMS code, an email code, a tax ID and a questionnaire in the same session.

The code comment added at useCardFlow.ts:193-197 states the problem and then discards it: "both tokens open the Rain verification level, which can ask for phone verification. An already-verified user is only completing the missing document" — the second sentence does not follow from the first.

This is the over-correction of the earlier P3 note: the answer is not to swap the Rain prep for the standard one. Either keep provider='rain' on main-kyc-required (accurate, at worst over-prepares), or drive the drawer off what is actually outstanding — the response already carries missingDocTypes, and the backend knows the applicant's remaining rain steps — rather than off the base verification status, which does not predict which Rain steps that applicant has completed.

Checked clean

  • Exact head, supplied base, merge base, trusted author, PR title, and description matched.
  • Token staging, drawer start/close transitions, refresh and reload paths, and CARD_SUMSUB_OPENED timing were traced.
  • The sibling API's main-kyc-required and incomplete branches and canonical Sumsub identity selection were checked.
  • The live Lexicon has no Rain-card prep or duration definition; product/card.md and the Rain compliance reference document the shared-KYC contract.
  • The Sumsub access token remains in component state and is not logged or persisted by this change.
  • Exact-head ci-success, unit, typecheck, eslint, format, native-export, and screen-tests checks are green; advisory visual captures were still running.
  • Focused local Jest was unavailable because the detached worktree has no node_modules; exact-head unit CI is green.
  • All four changed locale JSON files parse successfully and git diff --check is clean.

Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.

Third opinion by claude-opus: 2 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Exact head: 042209772123 · Context: repo, other-repo, product, notion-lexicon, ci · Took 16m

Comment thread src/i18n/app/messages/en.json Outdated
@innolope-dev

Copy link
Copy Markdown
Collaborator Author

Exact-head follow-up at 5602e32dc:

  • Rain prep now reuses retained identity documents for the normal approved-user path and shows only tax ID, SMS, email, and questionnaire requirements.
  • A verified user with a missing required selfie sees Rain extras plus only that selfie; new KYC still lists ID + selfie.
  • Standard KYC duration copy now says “a few minutes” in every app locale instead of an explicit 2-minute promise.
  • Companion content PR peanutprotocol/mono#187 at 5807a413 corrects product/providers/rain.md, product/help copy, and all repeated numeric 2/3-minute KYC strings and templates.

Validation: focused Jest 13/13, targeted ESLint, full typecheck, Prettier check, locale JSON parse, and git diff --check all pass.

@chip-peanut-bot chip-peanut-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip review — no blocking findings — this is not an approval

One major product-contract mismatch remains: the implemented Rain requirements pass and its 8-minute copy contradict the canonical no-second-pass, under-2-minute card verification model.

Findings

  • MAJOR · src/i18n/app/messages/en.json:2991 · Align the Rain prep with the card KYC contract
    At this head the drawer tells card applicants to expect an 8-minute Rain requirements pass. The canonical card and KYC sources still say the card reuses the existing Sumsub verification, has no card-specific second pass, and takes under 2 minutes for most users. A previously verified applicant therefore sees behavior and timing the product contract explicitly denies. Reconcile the product model before shipping: either remove or shorten the card-specific pass, or update the canonical product sources through product review and align this copy to the approved model.

Checked clean

  • Confirmed the detached worktree head, supplied base SHA, merge base, trusted author, PR number, and dev base ref exactly match the request.
  • Checked every supplied prior finding: main-KYC responses are now staged behind the prep drawer and CARD_SUMSUB_OPENED fires only after the user continues.
  • Checked the Rain checklist composition, all four locale bundles, and focused hook/component regressions; normal approved users no longer see retained ID and selfie requirements.
  • Checked the sibling API contract: both main-kyc-required and incomplete responses open the full Rain requirements level, including applicant data, phone and email verification, tax ID, and questionnaire steps; this refutes the claimed selfie-only timing defect but confirms the broader product-contract drift.
  • Fetched the live Notion Lexicon; it defines Sumsub/provider verification milestones but no card timing. The canonical product card, KYC, and Rain sources still promise token-sharing with no second pass and under-2-minute verification.
  • Checked exact-head CI: unit, typecheck, eslint, format, native export, screen tests, preview deployment, authorship, and review checks passed; locale visual captures and ds-shots were still running. git diff --check passed.
  • Checked security and privacy boundaries: the diff stages an existing Sumsub token in client state and adds no new auth, authorization, secret, money, or outbound-data surface.

Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.

Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Exact head: 5602e32dc124 · Context: repo, product, sibling-api · Took 16m

Comment thread src/i18n/app/messages/en.json Outdated

@chip-peanut-bot chip-peanut-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip review — no blocking findings — this is not an approval

The Rain prep flow now matches the backend contract, but the canonical card and KYC product sources still contradict the new card-specific verification stage.

Findings

  • MAJOR · src/components/Kyc/KycPrepChecklist.tsx:50 · Land the product-truth correction before this flow
    The new Rain branch tells an already-verified card applicant to complete provider-specific tax-ID, SMS, email, and questionnaire steps, while the current canonical card and KYC sources still promise that sharing the Sumsub dossier means there is no second card-verification pass. If this UI head lands first, help and product copy will send the same applicant into a flow they were explicitly told would not exist. Merge the companion canonical/content correction before this PR (or otherwise make that dependency enforceable) so the shipped flow and product truth change together.

  • MAJOR · src/i18n/app/messages/en.json:2962 · [claude-opus] Product truth still promises "no second pass" for the card
    This PR makes the card's extra verification explicit in the UI — it lists a tax ID, an SMS code, an email code and a questionnaire that the user must complete after their base KYC. peanut-api-ts confirms that is the reality: every token returned by /rain/apply (both incomplete and main-kyc-required) is minted for VERIFICATION_LEVELS.rain = rain-requirements, described at src/routes/rain/apply.ts:648-660 as "document collection, selfie, applicant data (incl. editable phone + TIN), phone verification, email verification, and the rain-card-extraInformation questionnaire".

Product truth says the opposite, in four places: product/card.md:23 (kyc_shared_with: rain # via Sumsub token sharing — no second KYC pass), product/card.md:113 ("Token-sharing avoids a second KYC pass"), product/card.md:191 ("users do not complete a second pass"), product/kyc.md:30-31 ("no second pass … no card-specific verification flow"), product/kyc.md:85 and product/quick-ref.md:140 ("shared with Rain via Sumsub token — no second pass"). The kyc.md:85 line is customer-facing privacy copy, and support answers derive from it.

The code is right and the docs are wrong. Token sharing removes the document re-upload, not the Rain level itself. Fix in product/: change the claim to something like "documents are reused via token sharing; the card adds a short Rain step — tax ID, phone and email codes, and a short questionnaire", and update card.md:23/113/191, kyc.md:30-31/85 and quick-ref.md:140 together, since support currently tells users there is no second step at all.

  • MINOR · src/i18n/app/messages/en.json:2990 · [claude-opus] Rain PR also relaxes the documented non-Rain KYC wait times
    Beyond adding howLong.rain, this PR rewrites two strings that have nothing to do with Rain, in all four locales: howLong.standard "Under 2 minutes for most people" → "A few minutes for most people" (en.json:2990), and howLong.hosted "About 5 minutes with your documents in hand" → "A few minutes with your documents in hand" (en.json:2992).

The standard path is the plain photo-ID + selfie flow, and product truth states its duration precisely: product/kyc.md:77 average_time: "Under 2 minutes for most users", repeated at kyc.md:150, and published on the live site (content/help-articles/help-center-index.md:24 "ID Check in Under 2 Min", plus content/use-cases//en.md, content/deposit//en.md — all "takes under 2 minutes"). After this merge the app tells a user one thing and peanut.me tells them another for the identical flow.

Secondarily, the new howLong.rain string is now character-for-character identical to howLong.standard, so the separate key conveys nothing: a flow with four extra steps (TIN entry, SMS code, email code, questionnaire) reads exactly as fast as ID + selfie alone.

The app copy is the wrong side to change here. Restore standard and hosted to the documented figures and let rain carry the vaguer wording — or, if the 2-minute figure is genuinely stale, update product/kyc.md:77 and the content pages in the same change rather than leaving the app as the only surface with the new number.

Checked clean

  • Verified the detached worktree head, trusted author, base ref, base SHA, and merge base against the supplied values.
  • Checked every apply-response path into Sumsub: incomplete and main-kyc-required responses stage the token behind the Rain prep drawer, while refresh and reload only resume a session the user already started.
  • Checked the sibling API contract and Rain readiness implementation: approved applicants reuse retained identity documents, missing main-level selfie is represented explicitly, and the Rain level requires tax ID, phone/SMS, email verification, and questionnaire data.
  • Fetched the live Notion Lexicon and checked the current canonical card, KYC, and Rain product sources; the provider-specific flow is still inconsistent with their no-second-pass promise.
  • Parsed all four changed locale files and checked key coverage, including es-AR inheritance; standard, Rain, and hosted automated durations now consistently use non-numeric few-minutes wording.
  • Checked exact-head CI: substantive unit, typecheck, lint, format, native export, preview deploy, and aggregate ci-success checks passed; advisory visual captures were still running. git diff --check also passed.

Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.

Third opinion by claude-opus: 2 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Exact head: 2e3b411d84d1 · Context: repo, product · Took 16m

Comment thread src/components/Kyc/KycPrepChecklist.tsx
@innolope-dev

Copy link
Copy Markdown
Collaborator Author

Exact-head review follow-up:

  • peanutprotocol/mono#187 is merged to main at bcfd756c, so the product-truth dependency now lands before UI PR Show Rain SMS requirement before card KYC #3185.
  • The two genuinely missed stale references (product/quick-ref.md and content/_system/data/spending-methods/virtual-card.md) are corrected in focused content PR peanutprotocol/mono#190 at ce635ed8.
  • Standard, Rain, and hosted automated KYC timing intentionally uses “a few minutes” per the user’s explicit direction; merged product/help content now uses the same non-numeric wording.
  • UI head remains 2e3b411d8; substantive CI is green. The screen-library publish job is advisory and failed after aggregate CI succeeded.

@innolope-dev
innolope-dev marked this pull request as draft September 15, 2026 15:29

This branch was successfully deployed

1 active deployment
Preview — 2e3b411d Deployed Sep 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant