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

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Sep 21, 2025

Summary by CodeRabbit

  • New Features
    • Enterprise workspaces can create/import links beyond usage limits; related tooltips no longer block actions for enterprise users.
    • Create Link and import interfaces now show upgrade tooltips only when limits are exceeded on non-enterprise plans.
    • Partners payouts now enforce a $10 minimum; attempts below this show a clear tooltip/message and are prevented.
    • Updated links limit notification email to display enterprise-specific messaging, removing the previous business-max path.

@vercel
Copy link
Contributor

vercel bot commented Sep 21, 2025

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

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Sep 21, 2025 10:54pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 21, 2025

Walkthrough

Enterprise plans are exempted from link usage limits across API, checks, UI gating, and email copy. Payouts now enforce a $10 minimum with corresponding UI tooltip. No public/exported API signatures changed; logic updates are conditional checks and UI tooltips.

Changes

Cohort / File(s) Summary
Links usage limit — backend checks
apps/web/app/api/links/bulk/route.ts, apps/web/lib/api/links/usage-checks.ts
Relax limit checks for enterprise: overage errors now thrown only when plan !== "enterprise".
Links usage limit — dashboard & modal UI
apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx, apps/web/ui/modals/link-builder/index.tsx
Tooltips/buttons gated by exceededLinks only when plan !== "enterprise"; enterprise keeps buttons active.
Email template copy
packages/email/src/templates/links-limit.tsx
“Enterprise” branch simplified; removed “business-max” special-case.
Partners payout minimum
apps/web/lib/actions/partners/confirm-payouts.ts, apps/web/ui/partners/payout-invoice-sheet.tsx
Enforce minimum payout of 1000 cents ($10) with early error; UI shows corresponding tooltip when amount < $10.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Web UI
  participant API as Bulk Links API
  participant UC as UsageChecks

  User->>UI: Create bulk links
  UI->>API: POST /api/links/bulk (links, workspace)
  API->>UC: checkLinksOverage(workspace, links.length)
  alt plan !== "enterprise" AND over limit
    UC-->>API: throw exceeded_limit
    API-->>UI: 4xx exceeded_limit
    UI-->>User: Show upgrade tooltip (non-enterprise)
  else enterprise OR within limit
    UC-->>API: ok
    API-->>UI: 200 created
    UI-->>User: Links created
  end
Loading
sequenceDiagram
  autonumber
  actor Partner
  participant UI as Payout Sheet
  participant ACT as confirmPayouts()
  participant Stripe as Stripe API

  Partner->>UI: Click Confirm Payouts
  UI->>ACT: confirmPayouts(amount)
  alt amount < $10 (1000 cents)
    ACT-->>UI: Error "minimum invoice amount $10"
    UI-->>Partner: Tooltip: minimum $10
  else amount ≥ $10
    ACT->>Stripe: Retrieve payment method
    ACT->>Stripe: Create invoice / payout
    Stripe-->>ACT: Success/Failure
    ACT-->>UI: Result
    UI-->>Partner: Show result
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Fix payouts limit #2577 — Also modifies confirm-payouts logic, likely adjacent to the new minimum payout validation.

Poem

A rabbit taps keys with a whiskered grin,
“Enterprise hops past the limit pen!”
Ten carrots minimum for payouts to flow,
Tooltips now whisper what users should know.
Links multiply, invoices align—
Thump-thump! Shipping time.
(_/) ✨ (•‿•) 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 succinctly reflects the PR's primary intent—completing TODOs related to updates for link limits and payout minimums—and aligns with the changes that adjust link overage behavior and add a payout minimum. It is concise, single-line, and avoids noisy elements like file lists or emojis.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch links-payouts-limit

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/ui/modals/link-builder/index.tsx (1)

281-287: Bug: paste-to-create is still blocked for enterprise when exceeded.

Paste handler only checks !exceededLinks; enterprise should bypass the limit. Update the condition.

-      !existingModalBackdrop &&
-      !exceededLinks
+      !existingModalBackdrop &&
+      (plan === "enterprise" || !exceededLinks)
🧹 Nitpick comments (6)
apps/web/lib/api/links/usage-checks.ts (1)

20-23: Enterprise exemption is correct; consider centralizing plan checks.

LGTM on not throwing for enterprise. To avoid drift across files, consider a shared helper like isEnterprisePlan(plan) (or enum) and reuse it here and in routes/UI.

packages/email/src/templates/links-limit.tsx (1)

83-94: Fix copy: missing “to” (twice).

Reads awkwardly: “upgrade the … plan add more links.” Suggest:

-                All your existing links will continue to work, and we are still
-                collecting data on them, but you'll need to upgrade the{" "}
+                All your existing links will continue to work, and we are still
+                collecting data on them, but you'll need to upgrade to the{" "}
...
-                </Link>{" "}
-                add more links.
+                </Link>{" "}
+                to add more links.
apps/web/lib/actions/partners/confirm-payouts.ts (2)

62-66: Use a shared constant for the $10 minimum and reuse the message.

Hardcoding 1000 and the string here will drift from UI. Define a single source of truth and reference it.

-    if (amount < 1000) {
-      throw new Error(
-        "Your payout total is less than the minimum invoice amount of $10.",
-      );
-    }
+    if (amount < MIN_PAYOUT_CENTS) {
+      throw new Error(MIN_PAYOUT_ERROR);
+    }

Outside this hunk, add:

// top-level (shared location preferred, e.g., lib/partners/constants)
export const MIN_PAYOUT_CENTS = 1_000 as const;
export const MIN_PAYOUT_ERROR = `Your payout total is less than the minimum invoice amount of $${MIN_PAYOUT_CENTS / 100}.`;

14-22: Tighten schema: enforce integer, nonnegative cents.

Prevents negative or float values slipping in.

-  amount: z.number(),
-  fee: z.number(),
-  total: z.number(),
+  amount: z.number().int().nonnegative(),
+  fee: z.number().int().nonnegative(),
+  total: z.number().int().nonnegative(),
apps/web/ui/partners/payout-invoice-sheet.tsx (2)

503-505: Good: tooltip explains the $10 minimum. Also block the button for < $10.

Currently the button isn’t disabled when 0 < amount < $10; ConfirmPayoutsButton suppresses hold on disabledTooltip, but also set disabled for clarity. Reuse a shared constant.

-          disabled={
-            eligiblePayoutsLoading || !selectedPaymentMethod || amount === 0
-          }
+          disabled={
+            eligiblePayoutsLoading ||
+            !selectedPaymentMethod ||
+            amount === 0 ||
+            (amount !== undefined && amount < MIN_PAYOUT_CENTS)
+          }
...
-            ) : amount && amount < 1000 ? (
-              "Your payout total is less than the minimum invoice amount of $10."
+            ) : amount && amount < MIN_PAYOUT_CENTS ? (
+              MIN_PAYOUT_ERROR
             ) : (

Add near the top (or import from a shared constants module used by the server action):

const MIN_PAYOUT_CENTS = 1_000;
const MIN_PAYOUT_ERROR = `Your payout total is less than the minimum invoice amount of $${MIN_PAYOUT_CENTS / 100}.`;

135-169: Stale memo deps: include payoutFee/paymentMethodsLoading; drop plan.

finalPaymentMethods depends on payoutFee, not plan. invoiceData uses paymentMethodsLoading in render but it’s not a dep, risking a stale skeleton.

-  const finalPaymentMethods = useMemo(
+  const finalPaymentMethods = useMemo(
     () =>
       paymentMethods?.map((pm) => {
         const paymentMethod = PAYMENT_METHODS[pm.type];
         const base = {
           ...paymentMethod,
           id: pm.id,
           fee: calculatePayoutFeeForMethod({
             paymentMethod: pm.type,
             payoutFee,
           }),
         };
         ...
       }),
-    [paymentMethods, plan],
+    [paymentMethods, payoutFee],
   );
-  }, [amount, paymentMethods, selectedPaymentMethod, cutoffPeriod]);
+  }, [amount, paymentMethods, paymentMethodsLoading, selectedPaymentMethod, cutoffPeriod]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between feae0f0 and 8638109.

📒 Files selected for processing (7)
  • apps/web/app/api/links/bulk/route.ts (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx (1 hunks)
  • apps/web/lib/actions/partners/confirm-payouts.ts (1 hunks)
  • apps/web/lib/api/links/usage-checks.ts (1 hunks)
  • apps/web/ui/modals/link-builder/index.tsx (2 hunks)
  • apps/web/ui/partners/payout-invoice-sheet.tsx (1 hunks)
  • packages/email/src/templates/links-limit.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-06T07:59:03.120Z
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.

Applied to files:

  • apps/web/app/api/links/bulk/route.ts
⏰ 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 (6)
apps/web/app/api/links/bulk/route.ts (1)

45-47: Bulk limit check now exempts enterprise — consistent with usage checks.

Matches throwIfLinksUsageExceeded behavior. Keep it this way so non‑enterprise is blocked pre-create (>=) and over-create (>) while enterprise proceeds.

If clients rely on error codes, note this block uses exceeded_limit while throwIfLinksUsageExceeded throws forbidden. Verify downstream handling isn’t brittle.

packages/email/src/templates/links-limit.tsx (1)

74-81: Copy path for enterprise looks good.

Message is clear and aligned with the exemption.

apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx (2)

397-401: Tooltip gate respects enterprise — nice.

Import options are disabled with an upgrade tooltip only for non‑enterprise when exceeded. Matches API behavior.


403-407: Verify upgrade path.

Here we link to /${slug}/upgrade; elsewhere (payouts) we use /${slug}/settings/billing/upgrade. Confirm both routes exist or standardize.

apps/web/ui/modals/link-builder/index.tsx (2)

265-266: Create button gating matches enterprise policy.

Reading plan here is correct and consistent with other UI gates.


301-309: Upgrade tooltip gated for non‑enterprise only — good.

Matches server checks.

@steven-tey steven-tey merged commit 1fad525 into main Sep 21, 2025
8 of 9 checks passed
@steven-tey steven-tey deleted the links-payouts-limit branch September 21, 2025 23:02
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