Fix KYC user info upsert on reapproval - #70
Merged
Conversation
aledefra
marked this pull request as ready for review
June 25, 2026 14:36
Contributor
There was a problem hiding this comment.
Pull request overview
This PR makes KYC “GREEN” approval handling idempotent when a wallet already has an existing user_infos row (where blockchain_address is the PK), preventing duplicate-key failures during re-approval flows and ensuring email delivery does not block persisting an approved state.
Changes:
- Add
storage.CreateOrUpdateUserInfousing a Postgres/GORMON CONFLICT (blockchain_address) DO UPDATEupsert. - Use the new idempotent user-info persistence path for both
ApplicantReviewedGREEN andApplicantOnHoldGREEN flows. - Send the KYC confirmation email after successful persistence, and make email failures warning-only.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| storage/userInfoStorer.go | Adds a CreateOrUpdateUserInfo upsert helper for user_infos keyed by blockchain_address. |
| service/sumsubService.go | Switches GREEN approval paths to the idempotent user-info write and moves confirmed-email sending after persistence (warning-only on failure). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+68
to
+75
| if txUpdate.Error != nil { | ||
| txUpdate.Rollback() | ||
| return txUpdate.Error | ||
| } | ||
| if txUpdate.RowsAffected == 0 { | ||
| txUpdate.Rollback() | ||
| return gorm.ErrRecordNotFound | ||
| } |
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.
Summary
Fixes repeated KYC approval handling when a wallet already has a
user_infosrow.Root cause: Sumsub GREEN approval processing always called
CreateUserInfo, butUserInfo.BlockchainAddressis the primary key. When a user is approved, reset/moved back to pending, then approved again, the second approval can fail on duplicateblockchain_addressbefore KYC state is updated.Changes:
storage.CreateOrUpdateUserInfousing Postgres/GORMON CONFLICT (blockchain_address) DO UPDATE.ApplicantReviewedGREEN andApplicantOnHoldGREEN approval paths.UpdateAll.Notion task: https://app.notion.com/p/Issue-on-KYC-status-change-357d59ab66578056a359f900ab65c8fd?source=copy_link
Verification
gofmt -w service/sumsubService.go storage/userInfoStorer.gogit diff --check -- service/sumsubService.go storage/userInfoStorer.gogo test ./service -run 'Test_TrimWhitespacesAndToLower|Test_IncreaseCountMapOverLimit|TestSemaphore|TestNotificationEmailsForAccount_DeduplicatesConfirmedRecipients'go test ./proxy/handlers -run TestNonExistentgo test ./service -run '^$' -count=0go test -c ./storage -o <tmp>/storage.testBlocked locally:
go test ./storage -run TestNonExistentrequires local DB config; current config fails withlookup port=0: no such host.Critic Review
Ran three read-only critic passes:
UpdateAll; fixed by persisting approval state before warning-only email and using explicit upsert columns.ApplicantOnHoldGREEN; fixed by sharing the idempotent approved-user-info flow across both GREEN approval paths.