feat: Integrate KYC/AML provider with retry, status callbacks, and replayable audit trail - #903
Open
EmannuellaO wants to merge 1 commit into
Open
feat: Integrate KYC/AML provider with retry, status callbacks, and replayable audit trail#903EmannuellaO wants to merge 1 commit into
EmannuellaO wants to merge 1 commit into
Conversation
…s, and replayable audit trail Implements Revora-Backend#875 behind KYC_PROVIDER_ADAPTER_ENABLED: - KycProviderAdapter: hardened adapter with exponential-backoff retries around initiateCheck/getStatus; passthrough adapter preserves legacy behaviour when the flag is off. - Signed webhook callbacks: raw-body HMAC verification, timestamp-bound replay window, and per-provider-tx-id replay guard (InMemoryKycReplayGuard). - Replayable audit trail: every verified callback is persisted to the audit log keyed by provider_tx_id with provider, status, investor, and timestamps. - kyc_status/kyc_provider/kyc_reference_id columns (migration 061) surfaced through UserRepository with updateKycVerification. - Investment gate: when enabled, submissions are blocked until the investor's kyc_status is 'approved' (fail-closed) and the block is audit-logged. - Register endpoint exposes an optional onRegistered hook for post-signup KYC initiation; a throwing hook never fails the signup. - KYC initiate routes are now mounted at /api/v1/kyc; webhooks at /api/v1/kyc/webhooks (mounted before the JSON parser for byte-exact HMAcs).
|
@EmannuellaO Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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.
Closes #875
Summary
Provider-agnostic KYC/AML integration behind a single feature flag (
KYC_PROVIDER_ADAPTER_ENABLED, default off). When off, behaviour is byte-for-byte the legacy path (passthrough adapter, no webhooks, no gate).What changed
src/services/kyc/KycProviderAdapter.ts—KycProviderAdapterinterface,DefaultKycProviderAdapter(exponential-backoff retries configurable viaKYC_ADAPTER_MAX_RETRIES/KYC_ADAPTER_BASE_RETRY_DELAY_MS),PassthroughKycProviderAdapter,createKycProviderAdapterfactory,kycNotApprovedError().src/services/kyc/kycVerificationService.ts—KycReplayGuard/InMemoryKycReplayGuard(per-provider-tx-id claim/commit),parseKycCallbackEvent,KycVerificationService.recordVerifiedCallbackwriting a replayable audit trail (action = kyc.verification.received, keyed byprovider_tx_id), then mutatingkyc_status(flag on) or audit-only (flag off). Fail-closed on malformed payloads/unknown investors.src/routes/kycWebhooks.ts—POST /api/v1/kyc/webhookswith raw-body HMAC verification (kycWebhookAuth, dual-key rotation, timestamp replay window) and outcome mapping (accepted/duplicate/rejected/user_not_found).src/db/migrations/061_add_kyc_status_to_users.sql—kyc_status,kyc_provider,kyc_reference_idonusers(with CHECK constraint + index).src/db/repositories/userRepository.ts— KYC columns surfaced throughUser,CreateUserInput,UpdateUserInput, and newupdateKycVerification().InvestmentService.createInvestmentrejects submission unlesskyc_status = 'approved'(fail-closed) and writes an audit-log block entry.src/index.ts— mounts/api/v1/kyc(initiate) and, only when the flag is on,/api/v1/kyc/webhooksbefore the global JSON parser for byte-exact signatures; wires the adapter + signed jurisdiction route table intoKycRouter.onRegisteredhook on the register endpoint for post-signup KYC initiation; a throwing hook is logged but never fails the signup.Behaviour matrix
kyc_statusmutationChecks
npx tsc --noEmitclean for touched files (remaining repo errors are pre-existing).