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

Skip to content

Conversation

@devkiran
Copy link
Collaborator

@devkiran devkiran commented Nov 27, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Duplicate payout-method fraud events are now handled consistently (no special-case early return), yielding uniform reporting.
  • Refactor

    • Grouping for fraud events reworked to use a stable grouping key instead of partner-only identifiers, improving deduplication and resolution accuracy.
  • New Features

    • Automatic generation of a grouping key when needed to better cluster related fraud events.

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

@vercel
Copy link
Contributor

vercel bot commented Nov 27, 2025

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

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Nov 28, 2025 3:20am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 27, 2025

Walkthrough

Replaces partnerId-based grouping with a flexible groupingKey across fraud event lifecycle: removes special-case branch for "partnerDuplicatePayoutMethod", generates a nanoid groupingKey in webhook handling, and updates create/detect/resolve logic and group-key hashing to use groupingKey.

Changes

Cohort / File(s) Summary
API route
apps/web/app/(ee)/api/fraud/events/raw/route.ts
Removed the early-return special-case for "partnerDuplicatePayoutMethod", so events of that type now go through the standard parsing/return path.
Webhook handler
apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts
Imported nanoid, generate groupingKey via nanoid(10) when duplicate payout methods are detected, and include groupingKey in created fraud event payloads.
Create fraud events
apps/web/lib/api/fraud/create-fraud-events.ts
Introduced CreateFraudEventsInput[] with optional groupingKey; compute groupKey using groupingKey (fallback to partnerId), add id via createId, and pass groupingKey through in created event payloads.
Detect & resolve
apps/web/lib/api/fraud/detect-record-fraud-event.ts, apps/web/lib/api/fraud/resolve-fraud-events.ts
Switched new-group-key construction to pass groupingKey (instead of partnerId/batchId) into group-key creation and subsequent grouping/resolution logic.
Utilities / group key
apps/web/lib/api/fraud/utils.ts
Reworked createFraudEventGroupKey to accept a CreateGroupKeyInput ({ type, programId, groupingKey }), added internal createHashKey helper (SHA-256 β†’ base64url β†’ trimmed), and compute the group key from programId, type, and groupingKey.

Sequence Diagram(s)

sequenceDiagram
  participant Webhook as Stripe Webhook
  participant Handler as account-updated.ts
  participant FraudSvc as create-fraud-events.ts
  participant Utils as fraud/utils.ts
  participant DB as Database

  Webhook->>Handler: receive account.updated event
  Handler->>Handler: detect duplicate payout method -> nanoid(10) -> groupingKey
  Handler->>FraudSvc: createFraudEvents([{ programId, partnerId, type, groupingKey }])
  FraudSvc->>Utils: createFraudEventGroupKey({ programId, type, groupingKey })
  Utils-->>FraudSvc: groupKey (hashed)
  FraudSvc->>DB: insert fraud events with groupKey, groupingKey, id
  DB-->>FraudSvc: insert result
  FraudSvc-->>Handler: created event payloads returned
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus areas:
    • Correctness of createHashKey (SHA-256, base64url encoding, trimming) in apps/web/lib/api/fraud/utils.ts
    • Proper fallback to partnerId where groupingKey may be undefined (create-fraud-events, detect logic)
    • Consistent propagation of groupingKey and inclusion of generated id across create/detect/resolve flows
    • Collision/entropy assumptions for nanoid(10) in webhook handler

Possibly related PRs

  • Fraud improvementsΒ #3159 β€” Modifies fraud detection/recording code and touches apps/web/lib/api/fraud/detect-record-fraud-event.ts, likely overlapping behavior changes.

Suggested reviewers

  • devkiran

Poem

🐰 I hop through code with keys in paw,

Nanoid seeds and hashed guffaw.
Events now group with a nimble string,
I munch duplicates and proudly sing.
Hooray β€” the rabbit stamps them in a ring! πŸŽ‰

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% 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 'Fix duplicate payout fraud event' directly corresponds to the main change: refactoring the duplicate payout method fraud event handling with improved grouping key logic across multiple 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-duplicate-payout-fraud-event

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

🧹 Nitpick comments (1)
apps/web/lib/api/fraud/utils.ts (1)

37-42: Outdated comment references partnerId instead of artifactKey.

The comment on lines 38-40 mentions "partnerId" but the interface field is now artifactKey. This should be updated for consistency.

   /**
    * The batch ID used to group fraud events. This is used when resolving fraud events
    * to break grouping so resolved events are no longer grouped with pending events
-   * that share the same programId, partnerId, and type.
+   * that share the same programId, artifactKey, and type.
    */
   batchId?: string;
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between c0d036f and d2d36ad.

πŸ“’ Files selected for processing (6)
  • apps/web/app/(ee)/api/fraud/events/raw/route.ts (0 hunks)
  • apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts (2 hunks)
  • apps/web/lib/api/fraud/create-fraud-events.ts (1 hunks)
  • apps/web/lib/api/fraud/detect-record-fraud-event.ts (1 hunks)
  • apps/web/lib/api/fraud/resolve-fraud-events.ts (1 hunks)
  • apps/web/lib/api/fraud/utils.ts (1 hunks)
πŸ’€ Files with no reviewable changes (1)
  • apps/web/app/(ee)/api/fraud/events/raw/route.ts
🧰 Additional context used
🧠 Learnings (5)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2635
File: packages/prisma/schema/payout.prisma:24-25
Timestamp: 2025-07-11T16:28:55.693Z
Learning: In the Dub codebase, multiple payout records can now share the same stripeTransferId because payouts are grouped by partner and processed as single Stripe transfers. This is why the unique constraint was removed from the stripeTransferId field in the Payout model - a single transfer can include multiple payouts for the same partner.
πŸ“š 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/(ee)/api/stripe/connect/webhook/account-updated.ts
  • apps/web/lib/api/fraud/detect-record-fraud-event.ts
  • apps/web/lib/api/fraud/utils.ts
  • apps/web/lib/api/fraud/create-fraud-events.ts
  • apps/web/lib/api/fraud/resolve-fraud-events.ts
πŸ“š Learning: 2025-07-11T16:28:55.693Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2635
File: packages/prisma/schema/payout.prisma:24-25
Timestamp: 2025-07-11T16:28:55.693Z
Learning: In the Dub codebase, multiple payout records can now share the same stripeTransferId because payouts are grouped by partner and processed as single Stripe transfers. This is why the unique constraint was removed from the stripeTransferId field in the Payout model - a single transfer can include multiple payouts for the same partner.

Applied to files:

  • apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts
πŸ“š Learning: 2025-07-17T06:41:45.620Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.

Applied to files:

  • apps/web/lib/api/fraud/detect-record-fraud-event.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/lib/api/fraud/create-fraud-events.ts
🧬 Code graph analysis (2)
apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts (1)
apps/web/lib/api/fraud/create-fraud-events.ts (1)
  • createFraudEvents (13-39)
apps/web/lib/api/fraud/create-fraud-events.ts (3)
packages/prisma/client.ts (1)
  • FraudRuleType (17-17)
packages/prisma/index.ts (1)
  • prisma (3-9)
apps/web/lib/api/fraud/utils.ts (1)
  • createFraudEventGroupKey (54-60)
⏰ 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 (7)
apps/web/lib/api/fraud/utils.ts (2)

29-31: LGTM!

The hash function is well-implemented using SHA-256 with base64url encoding. The 24-character truncation (144 bits of entropy) provides sufficient uniqueness for group key generation while keeping the keys reasonably short.


54-59: LGTM!

The grouping logic correctly builds parts from programId, type, artifactKey, and optional batchId, filtering out undefined values and normalizing to lowercase before hashing. This ensures consistent and deterministic group key generation.

apps/web/lib/api/fraud/resolve-fraud-events.ts (1)

50-55: Verify artifactKey consistency for non-partnerId-based fraud events.

For fraud events like partnerDuplicatePayoutMethod that use a shared artifactKey (nanoid) across multiple partners during creation, resolving them using partnerId as the artifactKey will produce a different groupKey pattern. Since the resolution already generates a new batchId to break grouping, this may be acceptable, but verify this is the intended behavior.

If the original artifactKey needs to be preserved for resolved events, consider storing it in the FraudEvent model.

apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts (1)

108-117: LGTM - Key fix for duplicate payout fraud grouping.

Generating a shared artifactKey via nanoid(10) ensures all fraud events for partners with duplicate payout methods are grouped together under the same key. This correctly addresses the issue where previously each partner's fraud events would be grouped separately (by partnerId), making it difficult to resolve them as a cohesive set.

apps/web/lib/api/fraud/detect-record-fraud-event.ts (1)

102-106: LGTM!

For conversion-based fraud detection, using partner.id as the artifactKey is correct. This maintains the existing partner-specific grouping behavior while aligning with the updated interface that now accepts artifactKey instead of partnerId.

apps/web/lib/api/fraud/create-fraud-events.ts (2)

6-11: LGTM!

The interface design is clean with an optional artifactKey and clear inline documentation explaining the partnerId fallback behavior. This maintains backward compatibility for existing callers.


19-26: LGTM!

The nullish coalescing fallback (artifactKey ?? partnerId) correctly implements the documented default behavior, ensuring consistent groupKey generation whether an explicit artifactKey is provided or not.

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: 1

🧹 Nitpick comments (1)
apps/web/lib/api/fraud/utils.ts (1)

33-43: Clarify the artifactKey documentation.

The documentation states artifactKey "can be" partnerId or other identifiers, but it's now the primary grouping mechanism (replacing partnerId). Consider updating the comment to emphasize that artifactKey is the definitive grouping identifier and provide examples of when to use partnerId vs. other keys (e.g., payout method ID for duplicate payout detection).

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d2d36ad and 1b172f6.

πŸ“’ Files selected for processing (2)
  • apps/web/lib/api/fraud/resolve-fraud-events.ts (1 hunks)
  • apps/web/lib/api/fraud/utils.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2635
File: packages/prisma/schema/payout.prisma:24-25
Timestamp: 2025-07-11T16:28:55.693Z
Learning: In the Dub codebase, multiple payout records can now share the same stripeTransferId because payouts are grouped by partner and processed as single Stripe transfers. This is why the unique constraint was removed from the stripeTransferId field in the Payout model - a single transfer can include multiple payouts for the same partner.
πŸ“š 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/api/fraud/resolve-fraud-events.ts
  • apps/web/lib/api/fraud/utils.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 (1)
apps/web/lib/api/fraud/utils.ts (1)
packages/prisma/client.ts (1)
  • FraudRuleType (17-17)
⏰ 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 (2)
apps/web/lib/api/fraud/resolve-fraud-events.ts (1)

50-54: Verify the random artifactKey generation on resolution.

The new groupKey is created with a random nanoid(10) as the artifactKey. This means resolved events get a unique group key each time, isolating them from future events. However, this discards any original artifactKey context (e.g., payout method ID) that was used to group these events initially.

Is this behavior intentional? If the goal is to archive resolved events under a unique identifier, this makes sense. Otherwise, consider whether the original artifactKey should be preserved or reused.

apps/web/lib/api/fraud/utils.ts (1)

29-31: LGTM!

The hash key generation using SHA-256 and base64url encoding is appropriate for creating stable, collision-resistant group keys.

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

♻️ Duplicate comments (1)
apps/web/lib/api/fraud/utils.ts (1)

29-31: Minor cleanups: drop unnecessary non‑null assertion and confirm base64url support

Two small things here:

  1. CreateGroupKeyInput marks all fields as required, so the non‑null assertion in .map((p) => p!.toLowerCase()) is unnecessary. You can simplify to:
-export function createFraudEventGroupKey(input: CreateGroupKeyInput): string {
-  const parts = [input.programId, input.type, input.groupingKey].map((p) =>
-    p!.toLowerCase(),
-  );
+export function createFraudEventGroupKey(input: CreateGroupKeyInput): string {
+  const parts = [input.programId, input.type, input.groupingKey].map((p) =>
+    p.toLowerCase(),
+  );
  1. createHash("sha256").digest("base64url") depends on your Node runtime supporting the "base64url" encoding; if you’re still on an older Node, you may need to fall back to "base64" and post-process. Worth confirming against the deployed Node version.

Also applies to: 33-52

🧹 Nitpick comments (1)
apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts (1)

5-5: Consider using a deterministic groupingKey instead of nanoid(10) for this rule

Right now groupingKey is a fresh nanoid(10) per accountUpdated run, so repeated Stripe account.updated deliveries or reprocessing for the same payoutMethodHash will generate new groupKeys instead of reusing a stable grouping identifier. If you rely on groupKey for idempotency/dedup of partnerDuplicatePayoutMethod events, it may be safer to base groupingKey on the stable payoutMethodHash (or similar) rather than a random value.

Example adjustment:

-      const groupingKey = nanoid(10);
+      const groupingKey = payoutMethodHash;

That still gets hashed by createFraudEventGroupKey, so the raw fingerprint isn’t exposed, but keeps grouping stable across retries for the same underlying payout method.

Also applies to: 80-118

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 1b172f6 and bffccba.

πŸ“’ Files selected for processing (5)
  • apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts (2 hunks)
  • apps/web/lib/api/fraud/create-fraud-events.ts (1 hunks)
  • apps/web/lib/api/fraud/detect-record-fraud-event.ts (1 hunks)
  • apps/web/lib/api/fraud/resolve-fraud-events.ts (1 hunks)
  • apps/web/lib/api/fraud/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/lib/api/fraud/detect-record-fraud-event.ts
🧰 Additional context used
🧠 Learnings (6)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2635
File: packages/prisma/schema/payout.prisma:24-25
Timestamp: 2025-07-11T16:28:55.693Z
Learning: In the Dub codebase, multiple payout records can now share the same stripeTransferId because payouts are grouped by partner and processed as single Stripe transfers. This is why the unique constraint was removed from the stripeTransferId field in the Payout model - a single transfer can include multiple payouts for the same partner.
πŸ“š Learning: 2025-07-11T16:28:55.693Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2635
File: packages/prisma/schema/payout.prisma:24-25
Timestamp: 2025-07-11T16:28:55.693Z
Learning: In the Dub codebase, multiple payout records can now share the same stripeTransferId because payouts are grouped by partner and processed as single Stripe transfers. This is why the unique constraint was removed from the stripeTransferId field in the Payout model - a single transfer can include multiple payouts for the same partner.

Applied to files:

  • apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts
πŸ“š 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/(ee)/api/stripe/connect/webhook/account-updated.ts
  • apps/web/lib/api/fraud/resolve-fraud-events.ts
  • apps/web/lib/api/fraud/utils.ts
  • apps/web/lib/api/fraud/create-fraud-events.ts
πŸ“š Learning: 2025-07-17T06:41:45.620Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.

Applied to files:

  • apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.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
πŸ“š 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/lib/api/fraud/create-fraud-events.ts
🧬 Code graph analysis (3)
apps/web/app/(ee)/api/stripe/connect/webhook/account-updated.ts (1)
apps/web/lib/api/fraud/create-fraud-events.ts (1)
  • createFraudEvents (13-39)
apps/web/lib/api/fraud/utils.ts (1)
packages/prisma/client.ts (1)
  • FraudRuleType (17-17)
apps/web/lib/api/fraud/create-fraud-events.ts (3)
packages/prisma/client.ts (1)
  • FraudRuleType (17-17)
packages/prisma/index.ts (1)
  • prisma (3-9)
apps/web/lib/api/fraud/utils.ts (1)
  • createFraudEventGroupKey (47-53)
⏰ 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 (2)
apps/web/lib/api/fraud/resolve-fraud-events.ts (1)

49-54: New random group key on resolve looks consistent with the grouping model

Using createFraudEventGroupKey({ programId, type, groupingKey: nanoid(10) }) when resolving a group cleanly moves all events in that group to a new groupKey, avoiding clashes with any future pending groups for the same rule. No issues from a correctness/consistency standpoint.

apps/web/lib/api/fraud/create-fraud-events.ts (1)

2-2: GroupingKey fallback and typed input look solid

The new CreateFraudEventsInput plus groupingKey: groupingKey ?? partnerId cleanly preserves existing behavior for callers that don’t provide a custom key while enabling more flexible grouping where needed. Centralizing groupKey computation through createFraudEventGroupKey and using createId({ prefix: "fre_" }) per event also keeps the creation path consistent and explicit. No changes suggested here.

Also applies to: 6-11, 13-36

@steven-tey steven-tey merged commit d126bfc into main Nov 28, 2025
6 of 7 checks passed
@steven-tey steven-tey deleted the fix-duplicate-payout-fraud-event branch November 28, 2025 03:50
This was referenced Dec 5, 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.

3 participants