fix(quotas): unifier le décompte IA (BYOK, rollback) et combler les fuites
Centralise la réserve via ai-quota, corrige admin unavailable (-1), brancher les routes sans quota et le host-pays brainstorm, avec usage-meter élargi, noms de clusters, MCP et ajustements dashboard/insights. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,6 +3,9 @@ import { VALID_FEATURES } from './quota-utils';
|
||||
|
||||
export type SubscriptionTier = 'BASIC' | 'PRO' | 'BUSINESS' | 'ENTERPRISE';
|
||||
|
||||
/** Stored in PlanEntitlement.limitValue — feature explicitly disabled via admin. */
|
||||
export const ENTITLEMENT_UNAVAILABLE = -1;
|
||||
|
||||
/** Hardcoded defaults — used when DB is empty or unavailable. */
|
||||
export const FALLBACK_TIER_LIMITS: Record<
|
||||
SubscriptionTier,
|
||||
@@ -98,18 +101,24 @@ function buildLimitMapFromRows(
|
||||
|
||||
for (const row of rows) {
|
||||
map[row.tier][row.feature] =
|
||||
row.limitValue === null ? Infinity : row.limitValue;
|
||||
row.limitValue === null
|
||||
? Infinity
|
||||
: row.limitValue === ENTITLEMENT_UNAVAILABLE
|
||||
? ENTITLEMENT_UNAVAILABLE
|
||||
: row.limitValue;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/** Merge DB entitlements with FALLBACK for features added after admin seeding. */
|
||||
/** Merge DB entitlements with FALLBACK for features added after admin seeding.
|
||||
* Does NOT override ENTITLEMENT_UNAVAILABLE (-1) or explicit limits. */
|
||||
function mergeWithFallback(map: LimitMap): LimitMap {
|
||||
const fallback = fallbackToLimitMap();
|
||||
for (const tier of Object.keys(fallback) as SubscriptionTier[]) {
|
||||
for (const [feature, limit] of Object.entries(fallback[tier])) {
|
||||
if (map[tier][feature] === undefined) {
|
||||
const current = map[tier][feature];
|
||||
if (current === undefined) {
|
||||
map[tier][feature] = limit;
|
||||
}
|
||||
}
|
||||
@@ -157,7 +166,7 @@ export async function getLimitAsync(
|
||||
): Promise<number | undefined> {
|
||||
const map = await loadLimitMap();
|
||||
const limit = map[tier]?.[feature];
|
||||
if (limit === undefined) return undefined;
|
||||
if (limit === undefined || limit === ENTITLEMENT_UNAVAILABLE) return undefined;
|
||||
if (limit === Infinity) return Infinity;
|
||||
return limit;
|
||||
}
|
||||
@@ -184,9 +193,11 @@ export async function getAllEntitlementsForAdmin(): Promise<
|
||||
feature: r.feature,
|
||||
limitValue: r.limitValue,
|
||||
mode:
|
||||
r.limitValue === null
|
||||
? ('unlimited' as const)
|
||||
: ('limited' as const),
|
||||
r.limitValue === ENTITLEMENT_UNAVAILABLE
|
||||
? ('unavailable' as const)
|
||||
: r.limitValue === null
|
||||
? ('unlimited' as const)
|
||||
: ('limited' as const),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user