Skip to content

Let admins expire a spend-limit override at the next credit refresh - #29623

Open
avervaet wants to merge 1 commit into
avervaet/overage-limit-expirationfrom
avervaet/overage-refresh-expiry
Open

Let admins expire a spend-limit override at the next credit refresh#29623
avervaet wants to merge 1 commit into
avervaet/overage-limit-expirationfrom
avervaet/overage-refresh-expiry

Conversation

@avervaet

Copy link
Copy Markdown
Contributor

Summary

  • Stacked on Auto-expire pool cap overrides once their requested period lapses #29618. Adds nextCreditResetAt to GetUserSpendLimitResponse, resolved from the same Metronome billing-period data the members usage table already uses (getCachedSeatDataByUserId, Redis-cached) — no new Metronome plumbing needed, and it degrades to null (not an error) on any Metronome fetch failure so a spend-limit read never breaks on a Metronome outage.
  • In EditSpendLimitModal, replaces the single "expires on" date field with a three-way choice: Never / On a specific date / At next credit refresh. The third option is only shown when a next-reset date is actually resolvable, and pins the override's expiresAt to that resolved date at save time.

Test plan

  • npm run test -- lib/api/users/spend_limit.test.ts (front) — nextCreditResetAt resolves from mocked Metronome seat data and degrades to null on failure.
  • npm run test -- "members/[uId]/spend_limit.test.ts" (front-api) — nextCreditResetAt round-trips through GET.
  • Manually open "Edit limit" for a Metronome-billed member with an active seat/contract — verify the "At next credit refresh" option appears with the correct formatted date, and saving with it selected persists that date as expiresAt.
  • Verify the option is hidden (not shown, not a broken/empty option) for a workspace with no Metronome contract.

Deploy plan

🤖 Generated with Claude Code

Adds nextCreditResetAt to GetUserSpendLimitResponse, resolved from the
same Metronome billing-period data the members usage table already
uses (Redis-cached, degrades to null on any Metronome fetch failure
so a read never breaks on an outage).

In EditSpendLimitModal, replaces the single "expires on" date field
with a three-way choice: never / on a specific date / at next credit
refresh. The last option pins the override's expiresAt to the
resolved Metronome date at save time, so admins don't have to guess
or compute it by hand when granting a temporary increase.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
playground Ignored Ignored Jul 28, 2026 2:16pm
storybook Ignored Ignored Preview Jul 28, 2026 2:16pm

Request Review

@dust-agent dust-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Coding rules review for PR #29623.

expiresAt = spendLimit?.nextCreditResetAt ?? null;
break;
default:
assertNeverAndIgnore(expiryMode);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[GEN6] Prefer exhaustive switch + assertNever over if/else on union types

expiryMode is internal component state (not API data), so a missing case is a programming error. Use assertNever (which throws at runtime) instead of assertNeverAndIgnore (which silently swallows it).

Suggested change
assertNeverAndIgnore(expiryMode);
assertNever(expiryMode);

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.

1 participant