[Ready] Fix Alfredpay KYB flow and other miscellaneous changes for dashboard.#1271
Open
gianfra-t wants to merge 9 commits into
Open
[Ready] Fix Alfredpay KYB flow and other miscellaneous changes for dashboard.#1271gianfra-t wants to merge 9 commits into
gianfra-t wants to merge 9 commits into
Conversation
…s Alfredpay requires The KYB corridor had no contract coverage at all: every KYB fixture in the repo was asserted only against mocks we wrote from types we also wrote, so nothing had ever met the provider. Running the real sequence against the sandbox found that Alfredpay's KYB requirements had expanded without us noticing — sendKybSubmission rejects our payload with 110002 "Invalid field(s)", naming nine compliance questionnaire fields plus a fourth company document. No company KYB can be finalized today. Alfredpay self-describes the per-country set at GET …/penny/kybRequirements?country= (MEX and MX both resolve). Its required list matches the 110002 rejection exactly. The questionnaire is sent flat and stored nested under `questionnaire`; the shareholder registry uploads as fileType `shareholderRegistry` (undocumented — found by probing, the other spellings 422). `pep` is required for CO/US/AR but not MX. - AlfredpayKybQuestionnaire on SubmitKybInformationRequest, and SHAREHOLDER_REGISTRY on AlfredpayKybFileType. The questionnaire fields are optional only because the KYB form does not collect them yet; making them required would force either invented compliance answers or a form demanding inputs it lacks. The gap is documented and the live flow test is what covers it — the compiler will not. - alfredpayKybBusinessDetailsResponseSchema pins submissionId + relatedPersons[] .idRelatedPerson, the pair the document uploads key off. - Live details read against a fully populated sandbox company, and an opt-in (ALFREDPAY_CONTRACT_RUN_KYB_FLOW=1) end-to-end flow: every call is accepted and every shape holds. The submission is then FAILED by sandbox verification within ~30s because the uploads are blank placeholder images, which is the correct outcome for fake documents — noted in the test so nobody chases it. - Security spec: the requirement set, the conditional branches, the pep corridor delta, and the known UI gap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for vrtx-dashboard canceled.
|
✅ Deploy Preview for vortex-sandbox ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for vortexfi ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
… provider requires Alfredpay's KYB requirement set had grown past what the form asked for, so no company KYB could be finalized through the widget or dashboard: sendKybSubmission rejected every submission with 110002 naming nine questionnaire fields and the shareholder registry. Nothing caught it because every KYB fixture was a mock written from types we also wrote. GET .../penny/kybRequirements?country= self-describes the set, and it is the source of truth here. The questionnaire goes on a new screen between the company form and the uploads (FillingKybQuestionnaire), is sent flat alongside the company fields, and is stored by Alfredpay nested under `questionnaire`. Two conditionals mirror the provider's: transmitsCustomerFunds reveals the compliance-screening pair, isRegulatedBusiness reveals the business licence and AML policy documents. `pep` is required for CO/US/AR but not MX — the only field that differs by corridor, so the form always asks it. The wire type keeps the questionnaire required and the machine splits the form data so back-navigation restores what was entered. submitKybInformation validates the questionnaire and its conditionals server-side, so a client that omits them is rejected with 400 rather than reaching Alfredpay. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s KYB
Company KYB failed for real users at the representative's ID upload with a bare
`{"errorCode":111301,"errorMessage":"UNKNOWN_ERROR"}` that names no field. The cause is
the filename: Alfredpay's relate-person endpoint answers any non-ASCII byte in the
multipart filename with a 502, and macOS separates the time from AM/PM with U+202F — so
`Screenshot ... at 12.23.56 PM.png` is rejected while the same name retyped with an
ordinary space is accepted. Accented names ("Identificación oficial.png") fail the same
way. Verified against the sandbox on the customer and related person from the production
log: the failing call succeeds with a blank.png, and every size, mime type and ASCII name
tested passes. The company-document endpoint next door accepts these names, which is why
only this one step broke.
Alfredpay stores every upload under a generated {uuid}.{ext}, so the submitted name is
discarded on arrival and rewriting it loses nothing. Applied to all three uploads.
The sanitizer copies the bytes into a new File, which is load-bearing: under Bun,
new File([file], name), new Blob([file]) and FormData.append(field, file, name) all alias
or ignore their way back to the original name. The first attempt used append's filename
argument and passed against the live sandbox while doing nothing; the test asserts the
name that reaches the wire, which is what caught it.
The contract test never saw this because it sent "blank.png" — faithful to every part of
the flow except the one thing a real user controls. It now drives the flow with the
production filename.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…splays The link text was updated to support@vortexfinance.co but the href still opened support@vortex.co, so clicking it mailed the old address. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the Alfredpay KYB flow end-to-end (shared types/schemas, API validation, XState machine, widget + dashboard UI, and tests/spec) to match Alfredpay’s provider-defined requirements, fix related-person upload targeting, and harden file uploads against provider failures caused by non-ASCII multipart filenames.
Changes:
- Align KYB submission payload with Alfredpay’s
kybRequirementscontract by adding the compliance questionnaire fields and additional required/conditional KYB documents. - Fix KYB representative document uploads by selecting
idRelatedPersonfor the currentsubmissionId(avoids stale-business related-person IDs). - Sanitize upload filenames to ASCII before sending multipart requests to Alfredpay, with unit/contract/e2e test coverage and security-spec updates.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/services/alfredpay/types.ts | Extends KYB file types and introduces questionnaire typing to match provider requirements. |
| packages/shared/src/services/alfredpay/schemas.ts | Adds zod schema for KYB business details response including submissionId + idRelatedPerson. |
| packages/shared/src/services/alfredpay/alfredpayApiService.ts | Sanitizes multipart filenames by rebuilding uploads with ASCII-safe names. |
| packages/shared/src/services/alfredpay/alfredpayApiService.test.ts | Adds tests asserting the filename that actually reaches fetch is ASCII-sanitized. |
| packages/kyc/src/index.ts | Re-exports new KYB questionnaire schema/types and mapping helpers. |
| packages/kyc/src/alfredpay/types.ts | Splits KYB data into form vs questionnaire; adds new required/conditional document fields. |
| packages/kyc/src/alfredpay/schemas.ts | Adds KYB questionnaire schema and mapping helpers for two-step KYB collection. |
| packages/kyc/src/alfredpay/schemas.test.ts | Adds tests for questionnaire requiredIf logic and mapping behavior. |
| packages/kyc/src/alfredpay/machine.ts | Adds questionnaire step, merges payload at submit, uploads new docs, filters related persons by submissionId. |
| packages/kyc/src/alfredpay/machine.test.ts | Expands unit coverage and adds “recording API” tests for payload merge + uploaded document set. |
| docs/security-spec/05-integrations/alfredpay.md | Updates Alfredpay KYB invariants and requirements, including filename sanitization and submissionId-related-person selection. |
| apps/frontend/src/translations/pt.json | Adds KYB questionnaire + document labels in Portuguese. |
| apps/frontend/src/translations/en.json | Adds KYB questionnaire + document labels in English. |
| apps/frontend/src/components/Alfredpay/KybQuestionnaireScreen.tsx | New widget questionnaire step UI wired to kybQuestionnaireSchema/mapping. |
| apps/frontend/src/components/Alfredpay/KybFormScreen.tsx | Adds repPep field and repopulation support when navigating back. |
| apps/frontend/src/components/Alfredpay/KybBusinessDocsScreen.tsx | Adds shareholder registry + conditional regulated-business docs. |
| apps/frontend/src/components/Alfredpay/AlfredpayKycFlow.tsx | Wires the new questionnaire step into the widget KYB flow. |
| apps/dashboard/src/components/transfer/TransferForm.tsx | Simplifies FundingMethods usage (removes network label prop). |
| apps/dashboard/src/components/transfer/FundingMethods.tsx | Gates funding UI to “connect wallet only” and removes crypto-tab functionality. |
| apps/dashboard/src/components/recipients/RecipientsTable.tsx | Adjusts focus-visible class ordering on recipient row. |
| apps/dashboard/src/components/onboarding/alfredpay/KybQuestionnaireScreen.tsx | New dashboard questionnaire step UI using shared schema/mapping. |
| apps/dashboard/src/components/onboarding/alfredpay/KybFormScreen.tsx | Adds repPep and supports repopulating form values when navigating back. |
| apps/dashboard/src/components/onboarding/alfredpay/KybDocumentUploadScreen.tsx | Adds shareholder registry + conditional regulated-business docs and updates required file counts. |
| apps/dashboard/src/components/onboarding/alfredpay/AlfredpayKycFlow.tsx | Wires dashboard questionnaire step into onboarding flow. |
| apps/dashboard/e2e/transfer-mxn-journey.spec.ts | Skips transfer journeys while FundingMethods submit is gated off. |
| apps/dashboard/e2e/support/mockBackend.ts | Tracks KYB upload fileType values and returns submissionId in KYB details mock. |
| apps/dashboard/e2e/onboarding-alfredpay-mxn-kyb.spec.ts | Updates e2e to fill questionnaire and assert correct upload types/counts. |
| apps/dashboard/e2e/funding-gate.spec.ts | Adds e2e asserting the funding UI gate (no crypto tab / no submit button). |
| apps/api/src/tests/contracts/alfredpay.contract.test.ts | Adds live KYB details contract and an opt-in end-to-end KYB sandbox flow. |
| apps/api/src/tests/alfredpay-kyb-pending.integration.test.ts | Updates fixtures for questionnaire fields and adds validator tests + submissionId assertion. |
| apps/api/src/api/routes/v1/alfredpay.route.ts | Adds validateKybSubmission middleware to KYB submit route. |
| apps/api/src/api/middlewares/validators.ts | Implements validateKybSubmission enforcing questionnaire + conditional rules pre-provider. |
| apps/api/src/api/controllers/alfredpay.controller.ts | Includes submissionId in minimized KYB details response for clients. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+98
to
+99
| expectedMonthlyTransactions: z.number("Enter a number").int("Enter a whole number").min(0), | ||
| expectedMonthlyVolumeUsd: z.number("Enter a number").min(0), |
Comment on lines
+60
to
+62
| * Alfredpay's relate-person upload rejects any non-ASCII byte in the multipart filename with a | ||
| * bare 500 `{"errorCode":111301,"errorMessage":"UNKNOWN_ERROR"}`. Verified against the sandbox: | ||
| * `ñandú.png` and `acentuación.png` fail while `with space.png`, `parens(1).png` and |
Comment on lines
+215
to
+216
| <button className="btn btn-vortex-accent w-full" onClick={onBack} type="button"> | ||
| {t("components.alfredpayKycFlow.cancel")} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.