Skip to content

cost-alert.ts: missing costResetAt clipping and limitTotalUsd/limitDailyUsd checks #927

@sususu98

Description

@sususu98

Summary

src/lib/notification/tasks/cost-alert.ts has two gaps that cause incorrect alert behavior after quota resets and missing alerts for total/daily limits.

Problem 1: costResetAt not considered

The cost alert system queries raw time ranges without clipping by costResetAt:

// current (cost-alert.ts)
const cost5h = await sumKeyCostInTimeRange(keyData.id, range5h.startTime, range5h.endTime);

In contrast, rate-limit-guard.ts and all quota display paths correctly clip the start time:

// rate-limit-guard.ts (correct)
const keyCostResetAt = resolveKeyCostResetAt(key.costResetAt ?? null, user.costResetAt ?? null);
const clipStart = (start: Date) => costResetAt > start ? costResetAt : start;

Impact: After an admin resets a user's or key's quota, the rate limiter correctly counts from zero, but the alert system still fires based on pre-reset usage. Users receive false "approaching quota" notifications.

This affects both user-level costResetAt (existing) and key-level costResetAt (new in feat/key-cost-reset).

Problem 2: limitTotalUsd and limitDailyUsd not checked

The alert query only selects three limit types:

const keysWithLimits = await db.select({
  limit5h: keys.limit5hUsd,
  limitWeek: keys.limitWeeklyUsd,
  limitMonth: keys.limitMonthlyUsd,
  // limitTotalUsd - missing
  // limitDailyUsd - missing
}).from(keys).where(
  sql`${keys.limit5hUsd} > 0 OR ${keys.limitWeeklyUsd} > 0 OR ${keys.limitMonthlyUsd} > 0`
);

Impact: Keys with limitTotalUsd or limitDailyUsd set will never receive approaching-quota alerts for those periods.

Suggested Fix

  1. Join with users table to get user.costResetAt, and select key.costResetAt
  2. Use resolveKeyCostResetAt() to compute effective reset time per key
  3. Clip all time range starts with clipStart() before querying costs
  4. Add limitTotalUsd check using sumKeyTotalCost(keyHash, Infinity, resolvedResetAt)
  5. Add limitDailyUsd check using sumKeyCostInTimeRange with daily time range (respecting dailyResetTime and dailyResetMode)

Affected Files

  • src/lib/notification/tasks/cost-alert.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:corebugSomething isn't workingstaleIssue has had no activity for 30+ days

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions