export type Plan = "free" | "pro" | "legend"; export type VoiceProvider = "elevenlabs" | "openai" | "google" | "cartesia" | "azure"; export interface VoiceConfig { /** TTS-Provider für diesen Plan */ provider: VoiceProvider; /** Provider-spezifische Model-ID (optional) */ model?: string; /** Provider-spezifische Voice-ID (optional — fällt auf provider-default zurück) */ voiceId?: string; /** Tages-Quota in Sekunden. 0 = unlimited */ dailyQuotaSeconds: number; } export interface PlanLimits { // ─── Custom Domains ────────────────────────────────────────────────────── /** Max. eigene Domains — EIN gemeinsamer Pool für web + mail (Infinity = unbegrenzt) */ customDomains: number; /** Freigeschaltete Domain-Slots füllen sich wieder auf (Community-Promotion) */ domainRefill: boolean; // ─── Mail-Accounts ─────────────────────────────────────────────────────── /** Max. aktive Mail-Agenten (Infinity = unbegrenzt) */ mailAgents: number; /** Erlaubte Scan-Intervalle in Stunden */ mailIntervalOptions: number[]; // ─── Globale Blocklist ─────────────────────────────────────────────────── /** * 'curated' = kleiner Stub der bekanntesten Casino-Domains (Free). * 'full' = vollständige HaGeZi/ReBreak-Liste (~208k). * * Der Stub selbst ist in server/utils/curated-blocklist.ts definiert. * Die echte ~1-2k HaGeZi-Subset-Liste ist ein separates Daten-Ticket. */ globalBlocklist: "curated" | "full"; // ─── Community ─────────────────────────────────────────────────────────── /** Darf in der Community posten */ canPost: boolean; /** Darf Gruppen gründen */ canCreateGroup: boolean; /** Darf Domains direkt zur ReBreak Blocklist hinzufügen */ canAddToBlocklist: boolean; // ─── Geräte (zwei getrennte Konzepte!) ─────────────────────────────────── /** * Max. parallel eingeloggte App-Geräte pro Account (Anti-Account-Sharing). * Bezieht sich auf UserDevice (iOS/Android-App-Instanzen). */ maxAppDevices: number; /** * Max. stationäre Geräte (Mac/Windows) die per DNS geschützt werden. * Gilt für Magic-Bindings (UserDevice.magicDnsToken — Magic-Mac/Win-App) * sowie legacy ProtectedDevice. Pro: 1 (Hauptrisiko-Gerät am Desktop), * Legend: 2 ("lückenlos auf 5 Geräten" — 3 mobil + 2 stationär). */ maxProtectedDevices: number; // ─── AI-Coach ──────────────────────────────────────────────────────────── /** Primäres OpenRouter/Groq-Modell für KI-Coach */ aiModel: string; /** Fallback-Modelle (werden der Reihe nach versucht wenn primary fehlschlägt) */ aiModelFallbacks: Array<{ provider: "groq" | "openrouter"; model: string }>; /** AI-Provider: groq (Free/Pro) oder openrouter (Legend/Claude) */ aiProvider: "groq" | "openrouter"; // ─── TTS ───────────────────────────────────────────────────────────────── /** * Voice-Config: welcher TTS-Provider + Quota. * * Provider-Mapping (Cost-Reference 2026-05): * Free → Google TTS Neural2 (~$4/1M chars, 60s/day cap) * Pro → Cartesia Sonic-2 (~$4/1M chars, 300s/day cap, ~75ms first-byte) * Legend → ElevenLabs Turbo v2.5 (~$30/1M chars, unlimited) */ voice: VoiceConfig; } // Free-Tier ist entfallen — es gibt nur noch Pro + Legend. export const PLAN_LIMITS: Record, PlanLimits> = { pro: { customDomains: 10, domainRefill: true, mailAgents: 2, mailIntervalOptions: [1, 4, 8], globalBlocklist: "full", canPost: true, canCreateGroup: false, canAddToBlocklist: false, maxAppDevices: 1, maxProtectedDevices: 1, // 1 Desktop (Mac ODER Windows) — Hauptrisiko-Gerät schützen aiModel: "llama-3.3-70b-versatile", aiModelFallbacks: [ { provider: "groq", model: "llama-3.1-8b-instant" }, { provider: "openrouter", model: "meta-llama/llama-3.3-70b-instruct" }, ], aiProvider: "groq", voice: { provider: "cartesia", model: "sonic-3", // Cartesia Sonic-3 — 42 Sprachen inkl. Arabisch (sonic-2 konnte nur 15, kein ar) dailyQuotaSeconds: 300, // 5 Minuten/Tag }, }, legend: { customDomains: 20, domainRefill: true, mailAgents: Infinity, mailIntervalOptions: [1, 4, 8], globalBlocklist: "full", canPost: true, canCreateGroup: true, canAddToBlocklist: true, maxAppDevices: 3, maxProtectedDevices: 2, // "+2 weitere Geräte" (§0.5) aiModel: "anthropic/claude-3.5-haiku", aiModelFallbacks: [ { provider: "openrouter", model: "anthropic/claude-3-haiku" }, { provider: "groq", model: "llama-3.3-70b-versatile" }, ], aiProvider: "openrouter", // Legend → ElevenLabs Turbo v2.5, unlimited. Voice-Picker / lyraVoiceId greift. // (2026-06-08 war wg. ElevenLabs-Zahlungsproblem temporär auf Cartesia umgeleitet; // 2026-06-11 neuer Key + bezahlt → zurückgesetzt.) voice: { provider: "elevenlabs", model: "eleven_turbo_v2_5", dailyQuotaSeconds: 0, // Legend bleibt unlimited }, }, }; export function getPlanLimits(plan: string): PlanLimits { // Free-Tier ist entfallen — alles außer Legend bekommt Pro-Limits. // Legacy-Namen: premium → legend, standard → pro. if (plan === "legend" || plan === "premium") return PLAN_LIMITS.legend; return PLAN_LIMITS.pro; } /** * Kuratierter Stub der bekanntesten Glücksspiel-Domains für Free-User. * Diese Liste ist der Mechanismus — der echte ~1-2k HaGeZi-Subset * ist ein separates Daten-Ticket (TODO: Daten-Ticket anlegen). * * Wird in DNS-Blocklist-Endpoints und scan-internal verwendet wenn * limits.globalBlocklist === 'curated'. */ export const CURATED_BLOCKLIST_STUB: string[] = [ // DE / Offshore-Klassiker (Top-Tier-Traffic) "betway.com", "bet365.com", "888casino.com", "pokerstars.com", "williamhill.com", "bwin.com", "unibet.com", "partypoker.com", "casinoclub.com", "interwetten.com", "tipico.de", "betsson.com", "casumo.com", "leovegas.com", "mr-green.com", "jackpot.de", "sunmaker.com", "stargames.com", "mybet.com", "winner.com", "ladbrokes.com", "coral.co.uk", "paddypower.com", "betfair.com", "mrvegas.com", "slotsmillion.com", "casinoeuropa.com", "netbet.com", "platincasino.com", "euslot.com", ];