credit_packages, credit_ledger y columna legacy_unlimited en users. Índices para queries de saldo en tiempo real.0012_add_credits.sqlcredit_packages: id, name, amount, price_eur, stripe_price_idcredit_ledger: user_id, delta, reason, skill_id, created_atusers.legacy_unlimited BOOLEAN DEFAULT falseuser_credit_balance (SUM ledger por user_id)supabase gen typessupabase db reset --linked o migración 0012_rollback_credits.sqllegacy_unlimited. Sin UI aún.lib/credits/getBalance(userId) — consulta view user_credit_balancelib/credits/deductCredits(userId, skillId, amount) — inserta en ledger con validación atómicalib/credits/isLegacyUnlimited(userId) — bypass de descuentodeductCredits antes de ejecutardeductCredits falla si saldo insuficiente (no negativo)deductCredits aúncheckout.session.completed que añade créditos al ledger tras pago confirmado.POST /api/credits/checkout — crea sesión StripePOST /api/stripe/webhook — acredita ledgerstripe trigger checkout.session.completedCreditBalance en el header del usuario. Modal de compra con los 3 paquetes disponibles. Server-side rendering del saldo.CreditBalance: saldo + botón "Comprar créditos"CreditShopModal: 3 tarjetas de paquete con preciolegacy_unlimited/admin/credits con tabla de usuarios, saldo actual, historial de ledger y acción de ajuste manual (añadir/restar créditos)./admin/credits — tabla paginada de usuarios + saldo/admin/credits/[userId] — historial de ledger completolegacy_unlimited por usuarioadmin (middleware ya existente)/admin/credits/*skill_credit_costs: slug → créditosdeductCredits justo antes de llamar al LLMCREDITS_ENABLED=false deshabilita el middleware sin revertir códigoCREDITS_ENABLED flag y código muertocredits_deducted, funnel de compravercel rollback + script de limpieza de ledger si datos corruptos