fix(custom-domains): Per-Bucket-Limit-Check via Backend counts/limits

Web-/Mail-Limit getrennt gegen apiCounts/apiLimits geprueft (Single Source of
Truth); Legacy-Response ohne counts/limits faellt auf Backend-Rejection zurueck.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-05-21 18:09:42 +02:00
parent 35a71a9068
commit 2839564469

View File

@ -145,8 +145,20 @@ export function useCustomDomains(plan: Plan): UseCustomDomainsReturn {
const resolvedKind: 'web' | 'mail' = kind ?? (input.includes('@') ? 'mail' : 'web');
if (resolvedKind === 'web' && !isValidDomain(input)) return { ok: false, error: 'invalid_domain' };
if (resolvedKind === 'mail' && !input.trim()) return { ok: false, error: 'invalid_pattern' };
const tier = deriveTier(plan, domains);
if (tier.atLimit) return { ok: false, error: 'limit_reached' };
// Per-Bucket-Limit-Check via Backend-counts/limits (Single Source of Truth).
// Wenn API noch keine counts/limits geliefert hat (Legacy-Response) → skip,
// Backend rejected dann mit WEB_LIMIT_REACHED / MAIL_LIMIT_REACHED.
if (apiCounts && apiLimits) {
const bucket = resolvedKind;
const used = apiCounts[bucket] ?? 0;
const cap = apiLimits[bucket] ?? Infinity;
if (used >= cap) {
return {
ok: false,
error: bucket === 'mail' ? 'mail_limit_reached' : 'web_limit_reached',
};
}
}
const pattern = resolvedKind === 'web' ? normalizeDomain(input) : input.trim();
const body: Record<string, string> = { pattern };
if (kind !== undefined) body.kind = kind;