diff --git a/backend/server/api/custom-domains/index.post.ts b/backend/server/api/custom-domains/index.post.ts index 655c9d8..e5ad8cd 100644 --- a/backend/server/api/custom-domains/index.post.ts +++ b/backend/server/api/custom-domains/index.post.ts @@ -168,18 +168,25 @@ export default defineEventHandler(async (event) => { }); } - // Pre-check: domain already on the global blocklist? Don't burn a slot for - // something the 208k-domain global filter already covers. Return 200 with a - // flag so the frontend can surface "already protected, no slot needed" - // without the user paying for it. mail_domain is included in the same check - // because mail-domains land in the same blocklist set the daemon scans. - const db = usePrisma(); - const globalMatch = await db.blocklistDomain.findFirst({ - where: { domain: value, isActive: true }, - select: { domain: true }, - }); - if (globalMatch) { - return { alreadyGlobal: true, domain: value }; + // Pre-check NUR für Mail-Typen: ist die Domain schon in der globalen + // Blocklist? Dann keinen Slot verbrennen — der Mail-Daemon scannt dieselbe + // Blocklist, ein Custom-Slot wäre redundant. + // + // Für `web` BEWUSST NICHT: Web-Custom-Domains speisen die Layer-2-VIP-Liste + // (webContent / Family Controls) — eine SEPARATE Schicht von der globalen + // Layer-1-Blocklist (URL-Filter / VPN). Eine Domain in Layer 1 ist NICHT + // automatisch in der Layer-2-VIP-50; und Layer 2 ist gerade das Netz für den + // Fall, dass Layer 1 deaktiviert wird. Global gelistete Domains müssen also + // in die VIP aufgenommen werden können. + if (type !== "web") { + const db = usePrisma(); + const globalMatch = await db.blocklistDomain.findFirst({ + where: { domain: value, isActive: true }, + select: { domain: true }, + }); + if (globalMatch) { + return { alreadyGlobal: true, domain: value }; + } } // Per-type Slot-Limit prüfen