feat: integrate Didit identity verification for KYC compliance#440
Conversation
|
@Ekene001 is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds Didit identity verification: API client, UI components (verify button + Identity section), settings tab wiring, user type fields, auth profile cache invalidation on verification, and a runtime dependency on the Didit web SDK. Changes
Sequence DiagramsequenceDiagram
actor User
participant Frontend as Frontend (React)
participant Backend as Backend API
participant SDK as Didit SDK (`@didit-protocol/sdk-web`)
participant Didit as Didit Service
User->>Frontend: Click "Verify identity"
Frontend->>Backend: POST /api/didit/create-session
Backend-->>Frontend: Return session_token & url (mapped -> verification_url)
Frontend->>SDK: import & initialize DiditSdk.shared
Frontend->>SDK: set onComplete callback
Frontend->>SDK: startVerification({ url: verification_url })
SDK->>Didit: Open verification modal / communicate with service
User->>Didit: Complete / Cancel / Fail verification
Didit->>SDK: Emit completion result
SDK->>Frontend: Invoke onComplete callback
Frontend->>Frontend: onSuccess -> call onVerificationComplete -> invalidate cache
Frontend->>Backend: GET /users/me (refetch)
Backend-->>Frontend: Return updated user with identityVerificationStatus
Frontend->>Frontend: Update UI (badge/date)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
lib/api/types.ts (1)
69-71: Extract a sharedIdentityVerificationStatustype to avoid drift.The status union is now duplicated in
lib/api/types.tsandtypes/user.ts; centralizing it in one exported alias will keep both user models consistent over time.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/api/types.ts` around lines 69 - 71, Create a shared exported type alias named IdentityVerificationStatus (e.g., export type IdentityVerificationStatus = 'Approved' | 'Declined' | 'In Review' | null) and replace the inline union used by identityVerificationStatus in lib/api/types.ts (and the duplicate in types/user.ts) with this single exported alias so both modules import and reference the same centrally defined type to prevent drift; update imports/exports accordingly.components/didit/IdentityVerificationSection.tsx (1)
54-57: Use a typed const-arrow component declaration for consistency.Convert this exported function declaration to a const-arrow component with an explicit type annotation to match repo conventions.
As per coding guidelines,
**/*.{ts,tsx}: Prefer const arrow functions with explicit type annotations over function declarations.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/didit/IdentityVerificationSection.tsx` around lines 54 - 57, Convert the exported function declaration IdentityVerificationSection to a const-arrow component with an explicit type annotation: replace "export function IdentityVerificationSection({ user, onVerificationComplete }: IdentityVerificationSectionProps) { ... }" with a const declaration like "export const IdentityVerificationSection: React.FC<IdentityVerificationSectionProps> = ({ user, onVerificationComplete }) => { ... }", keeping the same props usage and body (including the IdentityVerificationSectionProps type), and ensure any default exports or named exports remain unchanged.components/didit/DiditVerifyButton.tsx (1)
18-25: Prefer a typed const-arrow component export here.This should follow the TS/TSX convention used in your guidelines to keep component declarations consistent.
As per coding guidelines,
**/*.{ts,tsx}: Prefer const arrow functions with explicit type annotations over function declarations.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/didit/DiditVerifyButton.tsx` around lines 18 - 25, Replace the current function declaration for DiditVerifyButton with a typed const-arrow component: export a const named DiditVerifyButton typed as React.FC<DiditVerifyButtonProps> (or React.FunctionComponent<DiditVerifyButtonProps>) and implement the component as a const arrow (const DiditVerifyButton: React.FC<DiditVerifyButtonProps> = ({ onSuccess, onError, onCancel, className, disabled = false, userId }) => { ... }), preserving the same prop names and default for disabled and keeping existing logic and export.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/me/settings/SettingsContent.tsx`:
- Around line 109-112: The verification callback currently only calls
fetchUserData (updating SettingsContent local state) so the global cached
profile used by useAuthStatus (and read by UserMenu.tsx) stays stale; update the
onVerificationComplete handler to also invalidate or refresh the global
auth/profile cache (e.g., call the auth context updater or a revalidation
function such as refreshAuth / invalidateProfileCache / revalidateAuth) so both
IdentityVerificationSection and useAuthStatus see the new verification state —
change the handler passed to IdentityVerificationSection to call fetchUserData
and the global refresh/invalidate function (or dispatch the auth/profile update
via the auth context) so the UserMenu badge updates immediately.
In `@components/didit/DiditVerifyButton.tsx`:
- Around line 63-68: The catch block in DiditVerifyButton (the try/catch that
currently does setError(message) and setLoading(false)) swallows startup
exceptions and never notifies the parent; update that catch to also call the
provided onError handler (e.g., props.onError or onError) with the original
Error (or the derived message) so the parent receives the failure, then preserve
the existing local state updates (setError and setLoading(false)); ensure you
pass the actual Error when available (e instanceof Error ? e : new
Error(message)) to keep rich error info.
In `@components/user/UserMenu.tsx`:
- Around line 73-83: The verified-badge condition is inverted: the avatar badge
block using isVerified currently renders when the user is NOT verified; in the
UserMenu component update the conditional so the <span> with the verified
<Image> (the block containing src='/verified.png' and alt='Verified') only
renders when isVerified is true (i.e., change the {!isVerified && ...} check to
isVerified && ...), leaving the markup and image props unchanged.
---
Nitpick comments:
In `@components/didit/DiditVerifyButton.tsx`:
- Around line 18-25: Replace the current function declaration for
DiditVerifyButton with a typed const-arrow component: export a const named
DiditVerifyButton typed as React.FC<DiditVerifyButtonProps> (or
React.FunctionComponent<DiditVerifyButtonProps>) and implement the component as
a const arrow (const DiditVerifyButton: React.FC<DiditVerifyButtonProps> = ({
onSuccess, onError, onCancel, className, disabled = false, userId }) => { ...
}), preserving the same prop names and default for disabled and keeping existing
logic and export.
In `@components/didit/IdentityVerificationSection.tsx`:
- Around line 54-57: Convert the exported function declaration
IdentityVerificationSection to a const-arrow component with an explicit type
annotation: replace "export function IdentityVerificationSection({ user,
onVerificationComplete }: IdentityVerificationSectionProps) { ... }" with a
const declaration like "export const IdentityVerificationSection:
React.FC<IdentityVerificationSectionProps> = ({ user, onVerificationComplete })
=> { ... }", keeping the same props usage and body (including the
IdentityVerificationSectionProps type), and ensure any default exports or named
exports remain unchanged.
In `@lib/api/types.ts`:
- Around line 69-71: Create a shared exported type alias named
IdentityVerificationStatus (e.g., export type IdentityVerificationStatus =
'Approved' | 'Declined' | 'In Review' | null) and replace the inline union used
by identityVerificationStatus in lib/api/types.ts (and the duplicate in
types/user.ts) with this single exported alias so both modules import and
reference the same centrally defined type to prevent drift; update
imports/exports accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 94633cb5-2447-4094-a6ec-031930abfa54
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/verified.pngis excluded by!**/*.png
📒 Files selected for processing (8)
app/me/settings/SettingsContent.tsxcomponents/didit/DiditVerifyButton.tsxcomponents/didit/IdentityVerificationSection.tsxcomponents/user/UserMenu.tsxlib/api/didit.tslib/api/types.tspackage.jsontypes/user.ts
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
hooks/use-auth.ts (1)
167-170:⚠️ Potential issue | 🟡 MinorAdd missing
routerdependency tologoutcallback.Line 167-170 has an empty dependency array while
logoutusesrouterobtained fromuseRouter(). Includerouterin the dependency array to comply with thereact-hooks/exhaustive-depsESLint rule.Proposed patch
- }, []); + }, [router]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/use-auth.ts` around lines 167 - 170, The logout useCallback currently omits router from its dependency array causing an ESLint hook dependency violation; update the useCallback declaration that defines logout (which calls authClient.signOut() and router.push('/')) to include router in the dependency array (e.g., [router]) so the callback properly captures the useRouter() value and satisfies react-hooks/exhaustive-deps.
🧹 Nitpick comments (1)
hooks/use-auth.ts (1)
9-28: Prefer typed const-arrow functions for new helpers.The newly added helpers use function declarations; in this codebase, these should be
constarrow functions with explicit type annotations.Proposed refactor
-export function invalidateAuthProfileCache() { +export const invalidateAuthProfileCache: () => void = () => { authProfileInvalidationListeners.forEach(listener => { listener(); }); -} +}; -function useAuthProfileInvalidationSignal() { +const useAuthProfileInvalidationSignal: () => number = () => { const [refreshSignal, setRefreshSignal] = useState(0); useEffect(() => { @@ }, []); return refreshSignal; -} +};As per coding guidelines, "Prefer const arrow functions with explicit type annotations over function declarations".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@hooks/use-auth.ts` around lines 9 - 28, The two function declarations should be converted to const arrow functions with explicit TypeScript types: change `export function invalidateAuthProfileCache()` to `export const invalidateAuthProfileCache: () => void = () => { ... }` and change `function useAuthProfileInvalidationSignal()` to `const useAuthProfileInvalidationSignal: () => number = () => { ... }`; preserve the implementation (state, useEffect, listener add/delete) and keep the export on `invalidateAuthProfileCache`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@hooks/use-auth.ts`:
- Line 64: Remove the "!profileLoading" check from the conditional that gates
profile refetches in both useAuth() and useAuthStatus(): find the if that
currently reads something like if (session && 'user' in session && session.user
&& !profileLoading) inside useAuth() and the analogous check inside
useAuthStatus(), and change them to only verify session presence (e.g., if
(session && 'user' in session && session.user)), so profileRefreshSignal changes
are not ignored while a load is in progress and invalidation signals can replay
after loading finishes.
- Line 10: The forEach call uses an expression-bodied arrow
(authProfileInvalidationListeners.forEach(listener => listener());) which can
trigger the lint rule about implicit returns; change the callback to a
block-bodied arrow so it does not implicitly return a value — e.g., update the
forEach invocation on authProfileInvalidationListeners to use (listener) => {
listener(); } so the listener() call is executed but no expression is returned.
---
Outside diff comments:
In `@hooks/use-auth.ts`:
- Around line 167-170: The logout useCallback currently omits router from its
dependency array causing an ESLint hook dependency violation; update the
useCallback declaration that defines logout (which calls authClient.signOut()
and router.push('/')) to include router in the dependency array (e.g., [router])
so the callback properly captures the useRouter() value and satisfies
react-hooks/exhaustive-deps.
---
Nitpick comments:
In `@hooks/use-auth.ts`:
- Around line 9-28: The two function declarations should be converted to const
arrow functions with explicit TypeScript types: change `export function
invalidateAuthProfileCache()` to `export const invalidateAuthProfileCache: () =>
void = () => { ... }` and change `function useAuthProfileInvalidationSignal()`
to `const useAuthProfileInvalidationSignal: () => number = () => { ... }`;
preserve the implementation (state, useEffect, listener add/delete) and keep the
export on `invalidateAuthProfileCache`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c21707ba-0e43-4ad0-b1cb-8cae684d5204
📒 Files selected for processing (4)
app/me/settings/SettingsContent.tsxcomponents/didit/DiditVerifyButton.tsxcomponents/user/UserMenu.tsxhooks/use-auth.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- app/me/settings/SettingsContent.tsx
- components/didit/DiditVerifyButton.tsx
- components/user/UserMenu.tsx
…istener execution
closes #439
This PR adds end-to-end Didit identity verification support to the app, including session creation, verification launch flow, and identity status display in user settings/profile surfaces.
What changed
Impact
Testing
Summary by CodeRabbit
New Features
Improvements