Recertif KYC Lemonway¶
Lemonway peut rouvrir un KYC update sur un investisseur déjà accepté (requirements[] type KYC_UPDATE, éventuellement restrictions KYC_OUTDATED). Bricks expose ça sur investorIdentityStatus — pas via un nouveau champ /me, et pas via le formulaire Excel admin (KYC Update Lemonway Form).
Le profile LENDER reste ACCEPTED. L'identité des déjà-onboardés se calcule avec computeAcceptedInvestorIdentity, pas avec profiles[].status.
Contrat : investorIdentityStatus.ts.
const updateStatus = union('requested', 'underAnalysis', 'declined')
const update = object({ status: updateStatus, dueDate: isoDate })
verified: { status: 'verified', update?: update }
outdated: { status: 'outdated', update: update }
verifiedreste le gate transactionnel (assertTransactionRights). AvantdueDate, l'investisseur peut encore investir.outdatedbloque — restrictionKYC_OUTDATEDou requirementOVERDUE. HTTP investisseur et création admin de withdraw :Customer.assertTransactionRights(['all']). Play Lemonway : le worker P2P etgetWaitingWithdrawToPlayexcluentoutdated(débit et crédit). Les WTwaitingdéjà créées restent en file, Lemonway n'est pas appelé.verified+updaten'est pas exclu.dueDate= ISO datetime du GET/accounts(isoDate), pas leDueDateYYYY-MM-DD du webhook 53.update.statusest recertif-only. On ne réutilise paswaitingForVerifier/incorrect(funnel initial, interdit de transacter).
Correspondances Lemonway → Bricks¶
Funnel initial — profiles[].status LENDER¶
| Lemonway | Bricks investorIdentityStatus |
|---|---|
UNDER_ANALYSIS |
{ status: 'waitingForVerifier' } |
REJECTED / DENIED |
{ status: 'incorrect', documents } |
ACCEPTED (1re fois) |
{ status: 'verified' } |
Recertif — requirements[] (KYC_UPDATE) + restrictions (KYC_OUTDATED)¶
| Lemonway | Bricks |
|---|---|
Pas de KYC_UPDATE ouvert (vide / undefined / ACCEPTED) |
{ status: 'verified' } |
REQUESTED / UNDER_ANALYSIS / REJECTED, sans KYC_OUTDATED |
{ status: 'verified', update } — peut encore transacter |
Restriction KYC_OUTDATED ou requirement OVERDUE |
{ status: 'outdated', update } — bloqué |
update.status : REQUESTED / OVERDUE → requested · UNDER_ANALYSIS → underAnalysis · REJECTED → declined.
Deux ACCEPTED distincts : profile LENDER (funnel, ne bouge pas pendant la recertif) vs requirement KYC_UPDATE (recertif validée → plus d'update ouvert).
stateDiagram-v2
verifiedIdle: verified
verifiedRefresh: verified + update
outdated: outdated bloqué
verifiedIdle --> verifiedRefresh: notif 53 REQUESTED
verifiedRefresh --> verifiedRefresh: UNDER_ANALYSIS ou REJECTED avant dueDate
verifiedRefresh --> verifiedIdle: requirement ACCEPTED
verifiedRefresh --> outdated: notif 54 KYC_OUTDATED ou OVERDUE
outdated --> outdated: resubmit UNDER_ANALYSIS ou REJECTED
outdated --> verifiedIdle: ACCEPTED, restriction levée
Le submit du widget ne clôture pas l'update. C'est ACCEPTED (ou la disparition de la requirement) qui clôture.
Sync¶
- Webhooks 53/54 →
/lemonway/account/requirement-changeetrestriction-change. Chaque webhook enqueue le jobmigrate-lemonway-onboarding-v1-to-v2(idempotent si déjà v2, rattrape un v1 restant). Compte déjà v2 (lemonway.account.id) : aussisyncInvestorKycStatus(tous les customers matchés). Compte encore v1 : le job écrit le JSONBcustomers.lemonway(dual-write tables lemonway SPV seulement) puissyncInvestorKycStatuspour chaque customer migré. Plusieurs customers / wallets LENDER distincts sur le même account : chacun passe v2.customerTypevsaccount.type: mismatch → pas de migration investor (Slack, sans retry). L'URL hosted recertif (POST /onboarding/v2/start-onboarding) reste bloquée parinvestor-already-has-bricks-account— traitement OPS (HelpCenter). Recertif SPV : alerte Slack OPS (pas d'UI), y compris après une migration v1→v2. Les hooks onboarding v2 (account-status-changed/profile-status-changed) n'enqueuent pas ce job. POST /administration/customers/:customerId/sync-kyc-statusresync le même chemin (compte, profil, wallet, requirements/restrictions).GET /onboarding/v2/profile-statusresync si le profile ou le JSONB requirements/restrictions a bougé. Le poll ne renvoie que le kind (investorIdentityStatusKind, y comprisoutdated) —update/dueDaterestent surGET /customers/me.GET /customers/mene sync pas.
onboardingId recertif = root GET /accounts/{id}, distinct du funnel. Persisté tant que KYC_UPDATE est ouvert, vidé à la clôture — sinon le cycle suivant reprendrait l'ancienne session hosted.
Relances Customer.io¶
Cron kyc-update-reminder-notifications (07:15 UTC). Un run fetch les investisseurs avec un investorIdentityStatus.update (deletedAt null) dont la dueDate (jour calendaire Europe/Paris de l'isoDate persisté) tombe aujourd'hui à J-60, J-30, J-14, J-7, J-3, J0, J+7 ou J+14. Recertif ouverte ≠ à relancer : on notifie requested et declined (verified+update ou outdated), pas underAnalysis (dossier déjà soumis, Lemonway en cours). Chaque offset déclenche son broadcast API-triggered ; la seule variable template est dueDate au format DD/MM/YYYY.
Widget¶
Le front rejoue POST /onboarding/v2/start-onboarding. L'API ne rappelle pas startOnboarding : elle resume le nouvel onboardingId recertif. verified sans update → onboarding.investor-onboarding-already-completed.
Pas d'UI recertif dédiée : funnel initial et recertif partagent le même écran widget.
App investisseur (mobile + web)¶
| Élément | Emplacement |
|---|---|
| Composant | LemonwayKYCScreen — projects/front-mobile-app/src/modules/accountStatus/screens/LemonwayKYCScreen/ (hors legacy/OnboardingScreen) |
| Route Expo | /(authenticated)/onboarding/lemonway |
| Hook API | useStartLemonwayOnboarding → POST /onboarding/v2/start-onboarding |
| Fin de parcours | postMessage Lemonway → ReactNativeWebView (natif) ou parent (iframe web) ; poll GET /onboarding/v2/profile-status en parallèle |
| Entrées recertif | Modales account status (RecertNeededModal, LockedModal, ErrorModal) → router.navigate('/(authenticated)/onboarding/lemonway') |
Compte doublon (investor-already-has-bricks-account) |
openModal(HelpCenterModal) — pas Zendesk |
Le formulaire profil investisseur (étape avant Lemonway) reste sur /onboarding ; seul le widget hébergé Lemonway vit sur /onboarding/lemonway.
Liens¶
- Suivi (volumes, conversion, webhooks non rattachés) : skill
recertif-kyc-recap - Relances cron :
kyc-update-reminder-notifications.cron-task.ts - Service :
investor-onboarding.service.ts - Endpoints : Onboarding, GET /customers/me
- Webhooks 53/54 : KYC update webhooks
- Doc Lemonway : Handling KYC updates