[READY] Feat/kyb deep link#1215
Conversation
✅ Deploy Preview for vortexfi ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
❌ Deploy Preview for vortex-sandbox failed. Why did it fail? →
|
There was a problem hiding this comment.
Pull request overview
Adds a partner-facing, quote-less KYB deep-link flow to the widget that routes business users through auth → region selection (optionally locked) → provider KYB/KYC → completion, while keeping attribution parameters (partner/session/apiKey) consistent with the quoted flow.
Changes:
- Introduces KYB deep-link search params (
kyb,kybLocked) and a region table (KYB_REGIONS) to drive routing + default locale behavior. - Extends the ramp/KYC XState machines with new KYB-specific states/events (region selection, BR tax-id step, post-auth routing, terminal completion screen).
- Updates BRLA subaccount creation to allow quote-less KYB (optional
quoteId), and adds UI steps + translations for region selection and CNPJ entry.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/endpoints/brla.endpoints.ts | Makes quoteId optional for BRLA subaccount creation requests to support quote-less KYB. |
| apps/frontend/src/types/searchParams.ts | Adds kyb / kybLocked URL parameters to the ramp search schema. |
| apps/frontend/src/translations/pt.json | Adds PT translations for region selector + CNPJ (KYB tax id) step. |
| apps/frontend/src/translations/en.json | Adds EN translations for region selector + CNPJ (KYB tax id) step. |
| apps/frontend/src/routes/{-$locale}.tsx | Applies default locale when a region-pinned KYB link is used (e.g. BR → pt-BR). |
| apps/frontend/src/pages/widget/index.tsx | Renders new KYB steps and a KYB completion screen; adjusts Avenia KYB/KYC routing for deep links. |
| apps/frontend/src/machines/types.ts | Adds kybLink context and new KYB-related machine events/targets. |
| apps/frontend/src/machines/ramp.machine.ts | Adds KYB entry event + new states (SelectRegion/KybRouting/EnterKybTaxId/KybLinkComplete/PostAuthRouting). |
| apps/frontend/src/machines/ramp.context.ts | Ensures kybLink is included/reset via initial/reset context. |
| apps/frontend/src/machines/kyc.states.ts | Routes KYC child selection via quote fiat token or KYB-selected fiat token; adjusts back behavior and completion target for KYB deep links. |
| apps/frontend/src/machines/actors/brla/createSubaccount.actor.ts | Skips quote-bound KYC status lookup and relaxes quoteId requirement when in KYB deep-link mode. |
| apps/frontend/src/hooks/useStepBackNavigation.ts | Hides back navigation on the region selector step. |
| apps/frontend/src/hooks/useRampUrlParams.ts | Detects KYB deep-link params and boots the machine directly into KYB mode. |
| apps/frontend/src/constants/kybRegions.ts | Adds the region-to-fiat/label/defaultLocale mapping and lookup helper. |
| apps/frontend/src/components/widget-steps/RegionSelectStep/index.tsx | Implements the KYB region selector UI step. |
| apps/frontend/src/components/widget-steps/KybTaxIdStep/index.tsx | Implements the BR-only CNPJ entry step for KYB deep links. |
| apps/frontend/src/components/ui/DropdownSelector.tsx | Tweaks dropdown trigger transition properties and disables initial mount animation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ebma
left a comment
There was a problem hiding this comment.
For the Brazil flow, instead of having one card where the user only enters the CNPJ, only to then get to another card where they enter the CNPJ and the name, I suggest we skip the first one and only show the second one if possible. ie. let's only ask the user about company name and CNPJ together, not in separate cards of the flow. Or is there a reason for this split?
When I go to http://localhost:5173/en/widget?kybLocked=MX, I immediately see the form for KYC but not KYB. Are we not supporting KYB in Mexico? I also don't see the option to switch between KYB and KYC for Mexico in the card.
Besides that, I think the rest is good. Let's address copilots code review comments and please also ask your agent to update the relevant files of the security-spec and adjust the openapi.json and also create a new markdown page that we can put into the API docs.
Drop the separate CNPJ-only step and enter the CNPJ together with the company name on the Avenia KYB form (editable only in the quote-less deep link; read-only when supplied by a quote). Validate it as CNPJ-only via a new useKYBForm requireCnpj flag so a business deep link can't resolve to an individual account. Only honor ?kybLocked= when the region code is valid, otherwise fall back to the open selector, and fix the region-code JSDoc.
In Alfredpay CheckingStatus, send business customers on API-based countries (MX/CO) to FillingKybForm instead of the individual KYC form, mirroring the existing CreatingCustomer branch.
With ?kybLocked= the region selector is skipped, so the first KYB screen has nothing to go back to and its GO_BACK is a guarded no-op. Hide the button there while keeping it on deeper KYB steps that own their back navigation.
Make createSubaccount quoteId optional in the OpenAPI spec, add a KYB Deep Link guide page (manifest entry included), and note quote-less subaccount creation in the BRLA security spec.
| defaultValues: { | ||
| [ExtendedAveniaFieldOptions.TAX_ID]: initialData?.taxId || taxIdFromStore || "", | ||
| [ExtendedAveniaFieldOptions.FULL_NAME]: initialData?.fullName || "" | ||
| }, |
| | `?kybLocked=BR` \| `MX` \| `CO` \| `US` | Selector skipped, region pinned, back navigation into the selector disabled. | | ||
| | `?kybLocked=BR` (specifically) | Additionally defaults the widget locale to `pt-BR`. An explicit locale in the path still wins (e.g. `/en/widget?kybLocked=BR` stays English). | | ||
| | unknown region code (e.g. `?kybLocked=ZZ`) | Degrades gracefully to the open selector; the region is **not** treated as locked. | | ||
|
|
||
| Region codes are case-insensitive. |
Quote-less KYB deep link with region selector
Adds a partner-facing deep link that takes business users straight into KYB verification - no quote required. Partners can send their users to the widget with a single URL and have them complete business verification for any supported region.
Flow
URL parameters
?kyb?kyb=BR|MX|CO|US?kybLocked=BR|MX|CO|US?kybLocked=BR(specifically)pt-BR(an explicit locale in the path still wins, e.g./en/widget?kybLocked=BR)?kybLocked=ZZ, bare?kybLocked)externalSessionId,partnerId, andapiKeyare forwarded in KYB mode, so partner/session attribution works the same as in the quoted flow.Implementation notes
kybLinkcontext object - all KYB deep-link state (fiatToken,regionLocked) lives in a single optional context object whose presence enables the mode. It is registered ininitialRampContext, soRESET_RAMPfully exits KYB mode.SelectRegion(region picker, auto-skipped when locked and resolved to a fiat token),KybLinkComplete(terminal success screen), andPostAuthRouting(a transient state that routes a successful login - token check or OTP - to the destination recorded inpostAuthTarget, replacing the duplicated transition branches inCheckAuth/VerifyingOTP). A chosen region routes straight to the sharedKYCnode; Brazil collects its CNPJ on the Avenia company form rather than on a dedicated step.?kybLocked=only pins the region when the code resolves to a known region. An unknown or empty code yieldsregionLocked: false, so the selector is shown with working back navigation instead of a dead-end.?kybLocked=, the parent KYCGO_BACKis an explicit guarded no-op (it would otherwise restart the child KYC machine). The back button is hidden on the locked KYB entry screen and on the region selector (the selector is the root of the flow). Deeper KYB steps that own their own back navigation keep the button.useKYBFormgains arequireCnpjflag; when the tax ID is user-typed (the quote-less deep link), it must be a CNPJ, so a "business" entry can't silently resolve to an individual account downstream.KYB_REGIONSmaps each region code to its fiat token (provider routing), label key, and optionaldefaultLocale. Adding Spanish for MX/CO later is a data-only change.BrlaCreateSubaccountRequest.quoteIdis now optional; the backend stores it as a nullableinitialQuoteId(provenance only, never an authorization input). The subaccount actor only requires a quote in the normal flow and skips the quote-bound KYC-status lookup in deep-link mode.transition-propertypreviously covered only colors), and the panel no longer animates on initial mount.Docs
docs/api/openapi/vortex.openapi.json) -createSubaccountquoteIdis now documented as optional, with the quote-less KYB deep-link case described.docs/api/pages/13-kyb-deep-link.md(registered in the Apidog page manifest) covering the flow, URL parameters, attribution, and embedding.docs/security-spec/05-integrations/brla.md) - documents quote-less subaccount creation and that the nullableinitialQuoteIddoes not weaken any access check.Testing
bun typecheckclean, Biome clean on changed files, frontend test suite passing (23/23).