Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Dec 1, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Ban actions now immediately resolve pending fraud events for the affected program when a partner is banned (single and bulk), preventing stale state.
    • Sequencing issues after confirming bans fixed so UI state updates reliably.
  • Improvements

    • Confirmation flows now await server-side operations before closing, improving consistency.
    • Added informational logging summarizing how many fraud events were resolved and which partner/program they relate to.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Contributor

vercel bot commented Dec 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Dec 1, 2025 2:28am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Walkthrough

Moved auto-resolution of pending fraud events out of the cron ban-processing route into partner ban actions; added logging of resolved counts; updated modal onConfirm callbacks to be asynchronous and awaited, and adjusted where cache invalidation (mutatePrefix) is invoked.

Changes

Cohort / File(s) Summary
Cron: ban process
apps/web/app/(ee)/api/cron/partners/ban/process/route.ts
Removed auto-resolution of pending fraud events for the current program; replaced concurrent Promise.all(resolve/create) with a single awaited createFraudEvents call for cross-program fraud events.
Partner ban actions
apps/web/lib/actions/partners/ban-partner.ts, apps/web/lib/actions/partners/bulk-ban-partners.ts
Import and invoke resolveFraudEvents immediately after updating program enrollments to banned (using commonWhere or programEnrollment IDs); call occurs before audit logs and job queuing.
Fraud API
apps/web/lib/api/fraud/resolve-fraud-events.ts
updateMany result destructured to { count }; added console.info logging summarizing how many events were resolved for each partnerId/programId group.
UI: modals & tables
apps/web/ui/modals/ban-partner-modal.tsx, apps/web/ui/modals/bulk-ban-partners-modal.tsx, apps/web/app/app.dub.co/.../program/fraud/fraud-event-groups-table.tsx, apps/web/app/app.dub.co/.../program/partners/partners-table.tsx
Changed onConfirm prop types to return Promise<void> and updated modal success flows to await onConfirm. Removed direct mutatePrefix from modals and moved/awaited cache invalidation calls to table components where used.
Manifest note
package.json
Included in manifest files changed (no API signature changes).

Sequence Diagram(s)

sequenceDiagram
    participant UI as Client (UI)
    participant Actions as Server Actions
    participant Cron as Server Cron Route
    participant FraudAPI as Fraud API
    participant DB as Database
    participant Audit as Audit / Queue

    Note over UI,Actions: New ban flow (single / bulk)
    UI->>Actions: request ban (single/bulk)
    Actions->>DB: update programEnrollment(s) set banned
    Actions->>FraudAPI: resolveFraudEvents(where: partner/program or enrollmentIds)
    FraudAPI->>DB: updateMany fraud_events (set resolved)
    FraudAPI-->>Actions: { count } resolved
    Actions->>Audit: create audit log / queue jobs
    Actions-->>UI: respond success
    Note over Cron: Cron route now only creates cross-program fraud events
    Cron->>DB: query bans
    Cron->>FraudAPI: createFraudEvents (cross-program)
    FraudAPI->>DB: insert fraud_events
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to:
    • apps/web/lib/actions/partners/ban-partner.ts and .../bulk-ban-partners.ts β€” ensure resolveFraudEvents targets correct records (commonWhere vs programEnrollment IDs) and handles concurrency/transactions appropriately.
    • apps/web/app/(ee)/api/cron/partners/ban/process/route.ts β€” confirm removal of in-cron resolution doesn't leave unresolved events in edge cases.
    • UI changes (onConfirm: () => Promise<void>) β€” verify all callers now return/await promises and that no unhandled promise rejections occur.
    • resolve-fraud-events.ts logging β€” ensure safe behavior when groups are empty and logs include correct identifiers.

Possibly related PRs

Suggested reviewers

  • TWilson023

Poem

🐰 I hopped from cron to action, quick and neat,
Resolved the noisy frauds with tidy feet.
I counted silent whispers, logged each little score,
Awaited prompts and mutatesβ€”then hopped off the floor. πŸ₯•

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title directly relates to the main change: resolving fraud events synchronously during partner banning operations, which is the central objective across multiple modified files.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-ban-resolve-events

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.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/lib/actions/partners/ban-partner.ts (1)

5-89: Beware partial‑failure window between update and waitUntil

The new resolveFraudEvents call is correctly wired and the shared commonWhere is a nice reuse. However, its placement introduces a new partial‑failure scenario:

  • prisma.programEnrollment.update succeeds and the partner is banned.
  • resolveFraudEvents then throws (DB blip, bug, etc.).
  • The action rejects before reaching waitUntil, so:
    • the caller sees an error even though the partner is already banned,
    • no audit log is recorded,
    • the cron /api/cron/partners/ban/process job is never enqueued,
    • pending fraud events for this partner/program are left unresolved,
    • a subsequent attempt to ban the partner hits the β€œalready banned” guard and never retries resolution.

If you want ban‑side effects (logging, cron job, and fraud‑event resolution) to be best‑effort rather than all‑or‑nothing, consider one of:

  • Wrapping resolveFraudEvents in a try/catch that logs but does not abort the ban flow:
try {
  await resolveFraudEvents({
    where: commonWhere,
    userId: user.id,
    resolutionReason: "Resolved automatically because the partner was banned.",
  });
} catch (error) {
  // TODO: inject your logging util instead of console
  console.error("Failed to resolve fraud events after ban", error, {
    partnerId,
    programId,
  });
}
  • Or, if you’re comfortable with asynchronous resolution, moving resolveFraudEvents into the waitUntil(Promise.allSettled([...])) block alongside the audit log and enqueue logic so its failures don’t affect the main action result.

If the current β€œfail the action if resolution fails” behavior is intentional, it’d be good to document that trade‑off, since it means a single transient failure can leave a banned partner without the usual post‑ban processing.

🧹 Nitpick comments (2)
apps/web/lib/api/fraud/resolve-fraud-events.ts (1)

56-71: Logging addition after updateMany looks good

Using the count from updateMany and logging per group adds useful observability without changing core behavior. Even if a race leaves count === 0, the log is still accurate, just something to be aware of. You may optionally include the fraud type or resolutionReason in the log if you want richer debugging context, but it’s not required.

apps/web/lib/actions/partners/bulk-ban-partners.ts (1)

4-79: Bulk fraud‑event resolution wiring looks correct

Hooking resolveFraudEvents into the bulk ban flow after the updateMany on programEnrollment ensures pending fraud events tied to those enrollments are resolved as part of the operation, which matches the intent of this PR. The relation filter on programEnrollment.id is an appropriate way to scope the events.

If you want to trim a tiny bit of duplication, you could hoist the IDs into a local array and reuse it in both updateMany and resolveFraudEvents:

const programEnrollmentIds = programEnrollments.map(({ id }) => id);

await prisma.programEnrollment.updateMany({
  where: { id: { in: programEnrollmentIds } },
  // ...
});

await resolveFraudEvents({
  where: {
    programEnrollment: {
      id: { in: programEnrollmentIds },
    },
  },
  userId: user.id,
  resolutionReason: "Resolved automatically because the partner was banned.",
});

Purely a nit; current code is functionally fine.

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 324c2c8 and 14f40dc.

πŸ“’ Files selected for processing (4)
  • apps/web/app/(ee)/api/cron/partners/ban/process/route.ts (1 hunks)
  • apps/web/lib/actions/partners/ban-partner.ts (3 hunks)
  • apps/web/lib/actions/partners/bulk-ban-partners.ts (2 hunks)
  • apps/web/lib/api/fraud/resolve-fraud-events.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (6)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.
πŸ“š Learning: 2025-11-24T09:10:12.536Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.

Applied to files:

  • apps/web/lib/actions/partners/bulk-ban-partners.ts
  • apps/web/app/(ee)/api/cron/partners/ban/process/route.ts
  • apps/web/lib/actions/partners/ban-partner.ts
  • apps/web/lib/api/fraud/resolve-fraud-events.ts
πŸ“š Learning: 2025-11-12T22:23:10.414Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 3098
File: apps/web/lib/actions/partners/message-program.ts:49-58
Timestamp: 2025-11-12T22:23:10.414Z
Learning: In apps/web/lib/actions/partners/message-program.ts, when checking if a partner can continue messaging after messaging is disabled, the code intentionally requires `senderPartnerId: null` (program-initiated messages) to prevent partners from continuing to send junk messages. Only conversations started by the program should continue after messaging is disabled, as a spam prevention mechanism.

Applied to files:

  • apps/web/lib/actions/partners/bulk-ban-partners.ts
  • apps/web/app/(ee)/api/cron/partners/ban/process/route.ts
  • apps/web/lib/actions/partners/ban-partner.ts
πŸ“š Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.

Applied to files:

  • apps/web/lib/actions/partners/bulk-ban-partners.ts
  • apps/web/app/(ee)/api/cron/partners/ban/process/route.ts
  • apps/web/lib/actions/partners/ban-partner.ts
πŸ“š Learning: 2025-11-24T08:55:31.332Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/app/(ee)/api/fraud-rules/route.ts:71-87
Timestamp: 2025-11-24T08:55:31.332Z
Learning: In apps/web/app/(ee)/api/fraud-rules/route.ts, fraud rules cannot be created in a disabled state. When using prisma.fraudRule.upsert, the create branch intentionally omits the disabledAt field (defaulting to null, meaning enabled), while the update branch allows toggling enabled/disabled state via the disabledAt field. This is a business logic constraint.

Applied to files:

  • apps/web/app/(ee)/api/cron/partners/ban/process/route.ts
  • apps/web/lib/actions/partners/ban-partner.ts
πŸ“š Learning: 2025-08-14T05:17:51.825Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2735
File: apps/web/lib/actions/partners/delete-reward.ts:33-41
Timestamp: 2025-08-14T05:17:51.825Z
Learning: In the partner groups system, a rewardId can only belong to one group, establishing a one-to-one relationship between rewards and groups. This means using Prisma's `update` method (rather than `updateMany`) is appropriate when updating groups by rewardId.

Applied to files:

  • apps/web/lib/api/fraud/resolve-fraud-events.ts
🧬 Code graph analysis (3)
apps/web/app/(ee)/api/cron/partners/ban/process/route.ts (1)
apps/web/lib/api/fraud/create-fraud-events.ts (1)
  • createFraudEvents (13-39)
apps/web/lib/actions/partners/ban-partner.ts (2)
packages/prisma/index.ts (1)
  • prisma (3-9)
apps/web/lib/api/fraud/resolve-fraud-events.ts (1)
  • resolveFraudEvents (6-75)
apps/web/lib/api/fraud/resolve-fraud-events.ts (1)
packages/prisma/index.ts (1)
  • prisma (3-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (1)
apps/web/app/(ee)/api/cron/partners/ban/process/route.ts (1)

158-166: Cross‑program fraud event creation remains consistent with rule design

The simplified block that only calls createFraudEvents for partnerCrossProgramBan on other approved programs is sound and matches the intent of handling cross‑program risk separately from current‑program resolution. This aligns with the earlier decision that partnerCrossProgramBan is a partner‑scoped rule handled via dedicated flows rather than per‑conversion evaluation. Based on learnings, this looks correct.

@steven-tey
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

βœ… Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/ui/modals/ban-partner-modal.tsx (1)

53-62: Consider adding error handling around the onConfirm callback.

If the optional onConfirm callback throws an exception (e.g., if cache invalidation via mutatePrefix fails), the error may not be caught, potentially leaving the user without proper feedback even though the server-side ban succeeded.

Apply this diff to add error handling:

 const { executeAsync, isPending } = useAction(banPartnerAction, {
   onSuccess: async () => {
-    await onConfirm?.();
+    try {
+      await onConfirm?.();
+    } catch (error) {
+      console.error("Failed to invalidate cache after ban:", error);
+      // Continue with success flow since server action succeeded
+    }
     toast.success("Partner banned successfully!");
     setShowBanPartnerModal(false);
   },
   onError({ error }) {
     toast.error(error.serverError);
   },
 });
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 14f40dc and 995d299.

πŸ“’ Files selected for processing (4)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx (3 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx (2 hunks)
  • apps/web/ui/modals/ban-partner-modal.tsx (3 hunks)
  • apps/web/ui/modals/bulk-ban-partners-modal.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (5)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.
πŸ“š Learning: 2025-10-15T01:05:43.266Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.

Applied to files:

  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx
πŸ“š Learning: 2025-10-15T01:52:37.048Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx:270-303
Timestamp: 2025-10-15T01:52:37.048Z
Learning: In React components with dropdowns or form controls that show modals for confirmation (e.g., role selection, delete confirmation), local state should be reverted to match the prop value when the modal is cancelled. This prevents the UI from showing an unconfirmed change. The solution is to either: (1) pass an onClose callback to the modal that resets the local state, or (2) observe modal visibility state and reset on close. Example context: RoleCell component in apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx where role dropdown should revert to user.role when UpdateUserModal is cancelled.

Applied to files:

  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx
  • apps/web/ui/modals/ban-partner-modal.tsx
  • apps/web/ui/modals/bulk-ban-partners-modal.tsx
πŸ“š Learning: 2025-11-24T09:10:12.536Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.

Applied to files:

  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx
πŸ“š Learning: 2025-11-24T08:55:31.332Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/app/(ee)/api/fraud-rules/route.ts:71-87
Timestamp: 2025-11-24T08:55:31.332Z
Learning: In apps/web/app/(ee)/api/fraud-rules/route.ts, fraud rules cannot be created in a disabled state. When using prisma.fraudRule.upsert, the create branch intentionally omits the disabledAt field (defaulting to null, meaning enabled), while the update branch allows toggling enabled/disabled state via the disabledAt field. This is a business logic constraint.

Applied to files:

  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (5)
apps/web/ui/modals/ban-partner-modal.tsx (1)

35-35: LGTM! Async onConfirm pattern improves flow control.

The change from synchronous to asynchronous onConfirm properly sequences post-confirmation side effects before UI updates (toast and modal close). The pattern ensures cache invalidation completes before the user sees success feedback.

Also applies to: 53-58, 191-191

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/fraud-event-groups-table.tsx (2)

97-100: LGTM! Cache invalidation correctly sequenced with UI updates.

The async onConfirm callbacks properly trigger cache invalidation via mutatePrefix, ensuring the fraud events table refreshes after a successful ban. The row selection reset (line 98) executes synchronously for immediate user feedback, followed by the awaited mutation.

Also applies to: 379-381


377-382: The partner field is always non-null for fraud events. The FraudEvent model in the Prisma schema defines partnerId: String as a required (non-nullable) field, and all fraud event creation paths explicitly set partnerId from a partner object. The schema validation in get-grouped-fraud-events.ts will always succeed because the database constraint ensures every fraud event has an associated partner. The code at lines 377-382 is safe and does not require a null check.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx (1)

173-175: LGTM! Consistent cache invalidation pattern.

The async onConfirm callbacks correctly trigger cache invalidation for the partners table after successful bans. The pattern is consistent with the changes in fraud-event-groups-table.tsx and properly awaits the mutation before allowing UI updates to proceed.

Note: The same error handling concern mentioned for ban-partner-modal.tsx applies hereβ€”if mutatePrefix throws, it may interrupt the success flow.

Also applies to: 639-641

apps/web/ui/modals/bulk-ban-partners-modal.tsx (1)

30-30: LGTM! Async onConfirm pattern matches the single ban modal.

The changes mirror those in ban-partner-modal.tsx, providing consistent behavior across both single and bulk ban operations. The async onConfirm callback is properly awaited before showing success feedback and closing the modal.

Note: The same error handling concern mentioned for ban-partner-modal.tsx applies here as well.

Also applies to: 56-62, 225-225

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx (1)

51-56: Async onConfirm for useBanPartnerModal matches expected modal flow

Switching onConfirm to async () => { onNext?.(); } is a good fit if useBanPartnerModal now awaits onConfirm; it preserves behavior while satisfying the async contract. As a minor consistency tweak, if useResolveFraudEventsModal also treats onConfirm as async and awaits it, you might consider wrapping that callback in async () => { onNext?.(); } as well, but it’s not strictly necessary if the type allows void | Promise<void>.

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 995d299 and 26daec0.

πŸ“’ Files selected for processing (1)
  • apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.
πŸ“š Learning: 2025-10-15T01:52:37.048Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx:270-303
Timestamp: 2025-10-15T01:52:37.048Z
Learning: In React components with dropdowns or form controls that show modals for confirmation (e.g., role selection, delete confirmation), local state should be reverted to match the prop value when the modal is cancelled. This prevents the UI from showing an unconfirmed change. The solution is to either: (1) pass an onClose callback to the modal that resets the local state, or (2) observe modal visibility state and reset on close. Example context: RoleCell component in apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx where role dropdown should revert to user.role when UpdateUserModal is cancelled.

Applied to files:

  • apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx
πŸ“š Learning: 2025-11-24T09:10:12.536Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.

Applied to files:

  • apps/web/ui/partners/fraud-risks/fraud-review-sheet.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

@steven-tey steven-tey merged commit 5dfd48b into main Dec 1, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the fix-ban-resolve-events branch December 1, 2025 02:33
@coderabbitai coderabbitai bot mentioned this pull request Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants