Repository navigation
KYC rework: Smart Paperwork Verification, setup status and account availability - #3620
innolope-dev wants to merge 185 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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. Comment |
🧪 UI test report — 🔴 3 failingSuites
🔴 Failing tests
📊 Coverage (unit)
⏱ 10 slowest test cases
|
Code-analysis diffPainscore total: 10579.15 → 11008.03 (+428.88) 🆕 New findings (1354)
…and 1334 more. ✅ Resolved (1041)
…and 1021 more. 📈 Painscore deltas (top movers)
|
# Conflicts: # android/app/src/main/java/me/peanut/wallet/MainActivity.java # ios/App/App.xcodeproj/project.pbxproj # ios/App/App/AppViewController.swift # src/context/authContext.tsx
Every KYC entry point read GET /users/kyc/plan first, and a failed read threw out of initiate and restart. An API without the route (UI or OTA ahead of the backend, a rollback), a 5xx or a timeout therefore blocked verification with an untranslated "KYC request failed", and the mount status sync silently stopped. A failed plan read now means the legacy flow, which works while the policy is absent and is refused with a coded answer while it is active. Three fixes for the policy-active flow ride along: - An approved user's feature ticks are sent only on Continue. Each tick ran the provider replan at once, so a mis-tap submitted the dossier to a provider; an unchanged Continue now just closes. - A cross-region or country-specific entry for an approved user goes to the enrolment initiate performs instead of the feature picker, which dropped the target country. - Closing the document list calls onManualClose like every other close, so drawers and modal state are released.
|
English · Español · Español (Argentina) · Português (Brasil) Review preview: fdc1307 → e89896b. Incomplete capture; unavailable states are listed in the report. |
When resuming a saved document attempt failed, the hook's generic catch
put the action's English error ("KYC request failed", "Invalid KYC
verification session") on screen, inside otherwise Spanish or Portuguese
copy. Both resume paths (initiate and restart identity) now show the
localized initiate/restart failure message and release the
user-initiated guard.
The resume action also read the body with a bare response.json(), so a
non-JSON gateway error surfaced a SyntaxError message. The body read now
falls back to null and the session check tolerates it.
The backend will only require document selection first from clients that can show the picker. Every POST /users/identity now sends x-kyc-document-selection: 1 so this client opts in, while older binaries keep the legacy initiate.
Every feature toggle re-plans and hands the picker a new plan object, which reset the route to the first one and wiped the chosen document type and issuing country. The picker now keeps the selected route while it is still offered and keeps each choice the new plan still allows; only switching routes starts the documents over. The features fieldset was disabled while the re-plan ran, which dropped keyboard and screen-reader focus from the checkbox just changed. It now stays enabled with aria-busy and ignores changes until the plan returns.
Slava, 2026-10-27: - "When two countries are compared in the sign up flow (for residence and citizenship different) the list is incorrect. Check what is shown for every country and make sure it's correct." - "Brazil is showing Bank transfer (USD, EUR, GBP, MXN) while Macedonia is not showing the currencies, even though they are available." Checked against the API for all 250 countries (intentAvailability, the engine the verification applies): the comparison was wrong for 178. - 176 countries read "Bank transfers where supported" although the bank feature opens USD, EUR and GBP accounts there (India, Turkey, Ukraine…). - Brazil and Argentina listed only Pix or Argentine transfers, missing the bank accounts the server also opens. - South Korea showed bank transfers the server refuses. The comparison and the payment plan now read GET /config/kyc-intents for the country (useKycIntents, cached an hour, no auth). With it, a country lists its local rail when the local feature is open, Bridge's USD, EUR and GBP accounts when the bank one is (plus MXN in Mexico, home currency first), and the card when Rain takes it. The bundled tier lists stay as the fallback when the read fails. Offers wait until the answer is in. The payment plan's options follow the same answer, and "Bank transfer" names its currencies for every residence that has it, not only next to a Pix or ARS option. Also fixed: - two pt-BR strings that read "a Peanut" (glossary test); - duplicate React keys in the payment-plan picker for Brazil and Argentina, where two options share the short label "Bank transfer"; - tests pinned to the old verified button and the retired-route target.
… into innolope/kyc3620-dev-merge2 # Conflicts: # src/components/Setup/Views/__tests__/Residence.test.tsx # src/components/Setup/components/ResidenceCompare.tsx
|
… into innolope/kyc-consistency-fixes-ui
The plan's documentRefusals names, per ID issuing country, the features
the user asked for that a provider refuses with that ID. In the picker an
ID that closes all of them is greyed with the reason; one that closes some
says which ("The Peanut card isn't available with this document") and
asks before Sumsub opens, pointing at a document from the residence when
that one has no such limit. Copy in en, es-419 and pt-BR.
…peanutprotocol/peanut-ui into innolope/kyc-refused-ids-ui
Slava could type any random number as his tax number and go on: Continue only waited for a non-empty field (or refused an ITIN), and the API's rejection surfaced late because the save runs behind the next screen. The API now names, on the tax field, the stdnum validators of the residence's tax numbers (`checks`, such as ["de.idnr"]). The tax step loads just those validators' country modules from stdnum (1.12.6, the version the API pins), one small chunk per country, and runs them as the user types: Continue stays disabled until one accepts the number, and "Check the number. It doesn't look right." shows once the number is whole, or when the field is left part-typed. While the chunk loads Continue waits; if it cannot load, the API's own check decides. A check this app does not know turns the live check off rather than refusing what the API would accept.
…peanutprotocol/peanut-ui into innolope/kyc-tax-id-checks-ui
The plan answer gained a required flow field; the mock still built it without one, which failed the typecheck.
The plan read now types flow as required, so the one mock without it failed the typecheck. A null flow is what the test meant: no document-first timeline, so the setup status opens.
Slava, 2026-10-28 (item 13): a verified user who moves to a restricted country loses the services that country restricts once the move is approved, and is warned before confirming it. The residence drawer compares what the server opens in the verified residence and in the new one (GET /config/kyc-intents) and names the services the move closes: the Peanut card, bank accounts, local bank transfers or QR payments. The save button then reads Move anyway. A first declaration, or a move that closes nothing, keeps the short notes as before. The closing itself happens on the server when the move is approved.
|
…peanutprotocol/peanut-ui into innolope/kyc-tax-id-checks-ui
The comparison was retitled "Link your profile to one country"; the prelude test still looked for the old heading.
… into innolope/kyc-consistency-fixes-ui
…peanutprotocol/peanut-ui into innolope/kyc-refused-ids-ui
|
… into innolope/kyc-consistency-fixes-ui
The comparison screen's title changed with its redesign; the test pinned the old words.
|
…peanutprotocol/peanut-ui into innolope/kyc-tax-id-checks-ui
… into innolope/kyc-consistency-fixes-ui # Conflicts: # src/features/paperwork-verification/__tests__/VerifySetupPrelude.test.tsx
|
…peanutprotocol/peanut-ui into innolope/kyc-tax-id-checks-ui
|
The KYC rework in the app, in one PR. It pairs with peanutprotocol/peanut-api-ts#1931.
Smart Paperwork Verification is the one new identity flow: Peanut asks only what the user's features need, then one Sumsub ID check runs. The API decides who gets it (
plan.flow, sent thex-kyc-paperwork-verification: 1header on every KYC call). Everyone else, including users with an existing applicant, keeps today's flow. The document-first picker is gone, and the client never sendsx-kyc-document-selection.Design: the "Extra Details Questionnaire" prototype and the screen-picks canvas.
The flow
/verifydirectly. If the KYC plan has not loaded yet, the tap waits for it, so a new-flow user never sees the old "Unlock account" drawer. The drawer stays for an outage, a region-restricted ID or a plan that fails to load.documentDefinitions, CordovawithPreferredDocumentDefinitions).Adding a feature later asks only its missing answers. A verified user who needs a different document restarts on the same list (
/verify?step=id&restart=1).After verification
KycSetupStatusDrawer): one row per picked feature. The states are Available, Setting up, Under review, Document needed, Terms needed, Agreements needed, Verify ID, and Not available (with the reason), each with its one step.GET /users/kyc/paperwork).available: falsewithaccount_unavailable_in_residenceis never offered. Examples: USD for Bangladesh, Pakistan, Kenya and nine more; EUR and GBP for the Central African Republic, Eritrea and Mali.CountryListno longer leaves a spinner on a country whose tap opened a drawer in place.PostHog
Every screen here reports to PostHog; names are in
analytics.consts.ts.kyc_paperwork_viewed→_steps_viewed→_steps_continued→_step_viewed→_step_submitted→_step_saved→_saved_viewed→_id_viewed→_id_submitted(with the row'ssource) →_id_outcome→_identity_submitted→_review_viewed→_verified_viewed. Then the proof-of-address and add-later events._field_error(server or typing),_step_rejected,_form_error,_why_opened,_picker_opened/_closed,_search_empty,_back,_residence_change_opened,_local_refused.kyc_setup_status_viewed/_action, with each row's state and reason.posthog.capture.Validation
/verify(flow, acceptance, document screen, restart, add-later, analytics), Home activation and follow-up, setup status, deposit accounts (the paperwork overlay: Bangladesh and Mali verdicts, held accounts, working rails, absent products), and i18n (including duplicate-value drift)./verify?__fixture=paperwork-verification-de,-midpoint,-reviewand-verified: the steps overview, the document list and its Other-documents drawer, "Checking your ID" and "Your ID is confirmed!" match the prototype./verify?__fixture=paperwork-verification-de(city search),-br,-ar,-us,-ph,-midpoint,-review,-verified,-proof-of-address,-add-card,-add-local,-save-fails;/history?__fixture=kyc-setup-*.openapi.json.Activation
Keep this a draft until sandbox acceptance. Deploy peanutprotocol/peanut-api-ts#1931 first, then this UI, then publish a checked policy. No native binary or tenant change is needed.
Known limit: entry points other than Home (the QR gate, deposit gates, withdraw) still show the start drawer first, and its Verify button then opens
/verify.