📐
Blueprint — Plan de Construcción

cultivaia-next: Sistema de Créditos para Skills IA

plans/cultivaia-next-sistema-creditos-ia.md  ·  Generado 18 Jun 2026  ·  Proyecto: cultivaia-next
7
Pasos / PRs
3
Paralelos
5
Fases
Pipeline de Generación
Fase 1
Investigación
Stack, DB, CI, planes existentes
Fase 2
Diseño
Pasos, dependencias, paralelismo
Fase 3
Redacción
Plan Markdown autocontenido
Fase 4
Revisión Adversarial
Sub-agente Opus · 14 checks
Fase 5
Registro
plans/ + memory index
Objetivo
"Añadir un sistema de créditos para el consumo de skills de IA: compra, descuento automático por uso y panel de gestión para el admin"
Serie (bloquea siguiente)
Paralelo (sin dependencias cruzadas)
Modelo fuerte (Opus)
Requiere revisión de tests
Plan de Construcción — 7 PRs
1
Migración de base de datos: tablas de créditos
Crear credit_packages, credit_ledger y columna legacy_unlimited en users. Índices para queries de saldo en tiempo real.
infra serie Opus (diseño de schema)
Rama
feat/credits-schema
Depende de
  • Crear migración SQL 0012_add_credits.sql
  • Tabla credit_packages: id, name, amount, price_eur, stripe_price_id
  • Tabla credit_ledger: user_id, delta, reason, skill_id, created_at
  • Columna users.legacy_unlimited BOOLEAN DEFAULT false
  • View user_credit_balance (SUM ledger por user_id)
  • RLS: users ven solo su propio ledger; admin ve todo
  • Migración aplica sin errores en staging
  • View devuelve balance correcto para user de prueba
  • RLS impide acceso cruzado entre users (test manual)
  • Tipos TypeScript generados por supabase gen types
supabase db push --db-url $SUPABASE_DB_URL && supabase gen types typescript --local > types/supabase.ts && npx tsc --noEmit
Rollback: supabase db reset --linked o migración 0012_rollback_credits.sql
2
Capa de servicio: lógica de créditos en el servidor
Server Actions de Next.js para consultar saldo, descontar créditos por skill y verificar flag legacy_unlimited. Sin UI aún.
serie tests unitarios
Rama
feat/credits-service
Depende de
Paso 1
  • lib/credits/getBalance(userId) — consulta view user_credit_balance
  • lib/credits/deductCredits(userId, skillId, amount) — inserta en ledger con validación atómica
  • lib/credits/isLegacyUnlimited(userId) — bypass de descuento
  • Middleware de skill: llama deductCredits antes de ejecutar
  • Invariante: saldo nunca negativo (check en DB)
  • deductCredits falla si saldo insuficiente (no negativo)
  • Legacy users pasan sin descuento
  • Tests unitarios pasan: 8 casos (saldo ok, insuficiente, legacy, concurrencia)
  • CI verde en PR
pnpm test lib/credits && pnpm tsc --noEmit
Rollback: Revertir PR; el middleware no llama a deductCredits aún
PARALELO — Pasos 3, 4 y 5 sin dependencias cruzadas
3
Integración Stripe: paquetes de créditos + webhook
Productos en Stripe para cada paquete de créditos. Webhook checkout.session.completed que añade créditos al ledger tras pago confirmado.
paralelo stripe
Rama
feat/credits-stripe
Depende de
Paso 2
  • Crear 3 productos en Stripe: 100, 500, 2000 créditos
  • Endpoint POST /api/credits/checkout — crea sesión Stripe
  • Webhook POST /api/stripe/webhook — acredita ledger
  • Test webhook con stripe trigger checkout.session.completed
  • Pago de prueba acredita saldo correctamente
  • Webhook idempotente (2 eventos iguales no duplican créditos)
  • Firma de webhook verificada (no se aceptan eventos sin firma)
stripe trigger checkout.session.completed && pnpm test api/stripe
4
UI: widget de saldo y flujo de compra en el dashboard
Componente CreditBalance en el header del usuario. Modal de compra con los 3 paquetes disponibles. Server-side rendering del saldo.
paralelo
Rama
feat/credits-ui-user
Depende de
Paso 2
  • Componente CreditBalance: saldo + botón "Comprar créditos"
  • Modal CreditShopModal: 3 tarjetas de paquete con precio
  • Estado optimista al descontar créditos (UX sin lag)
  • Toast de error si saldo insuficiente al lanzar skill
  • Ocultar controles para usuarios legacy_unlimited
  • Saldo renderizado SSR (no flash 0 → real)
  • Legacy users no ven el widget de compra
  • Tests de componente: 6 casos (estados loading, saldo, compra, error)
pnpm test components/credits && pnpm build --no-lint
5
Panel admin: gestión de créditos por usuario
Nueva sección /admin/credits con tabla de usuarios, saldo actual, historial de ledger y acción de ajuste manual (añadir/restar créditos).
paralelo
Rama
feat/credits-admin
Depende de
Paso 2
  • Ruta /admin/credits — tabla paginada de usuarios + saldo
  • Detalle /admin/credits/[userId] — historial de ledger completo
  • Acción de ajuste manual con campo de razón (auditoría)
  • Toggle legacy_unlimited por usuario
  • Protección: solo rol admin (middleware ya existente)
  • Ajuste manual refleja en ledger con razón auditada
  • No-admin recibe 403 en todas las rutas /admin/credits/*
  • Export CSV de ledger funciona para soporte
pnpm test app/admin/credits && curl -H "Authorization: Bearer $USER_TOKEN" /api/admin/credits -w "%{http_code}" | grep 403
6
Integración end-to-end: activar descuento en skills existentes
Conectar el middleware de créditos con el flujo de ejecución de skills. Definir tabla de costes por skill. Tests de integración completos.
serie tests e2e Opus (revisión de regresiones)
Rama
feat/credits-wire-skills
Depende de
Paso 3 Paso 4 Paso 5
  • Tabla skill_credit_costs: slug → créditos
  • Invocar deductCredits justo antes de llamar al LLM
  • Si falla el LLM, revertir el descuento (compensación en ledger)
  • Tests e2e Playwright: flujo completo compra → usa skill → saldo correcto
  • Smoke test en staging con usuarios reales legacy
  • Skills existentes funcionan sin cambio para legacy users
  • Nuevo user sin créditos ve error claro (no error 500)
  • Crédito compensado si skill falla tras descuento
  • Tests e2e pasan en staging
pnpm test:e2e --project=credits && pnpm test:e2e --project=legacy-users
Rollback: Feature flag CREDITS_ENABLED=false deshabilita el middleware sin revertir código
7
Limpieza y activación en producción
Eliminar feature flag, migrar a producción, actualizar documentación interna y activar monitoreo de saldo en PostHog.
serie producción
Rama
feat/credits-launch
Depende de
Paso 6
  • Eliminar CREDITS_ENABLED flag y código muerto
  • Migración en producción Supabase (ventana de mantenimiento 5 min)
  • PostHog: evento credits_deducted, funnel de compra
  • Sentry: alert si tasa de errores de créditos > 1% en 5 min
  • Email de anuncio a usuarios activos (Resend)
  • Producción estable 30 min post-migración
  • PostHog registra eventos de compra y descuento
  • Cero errores relacionados con créditos en Sentry (primera hora)
  • Legacy users sin impacto verificado
pnpm build && vercel --prod && pnpm test:smoke --env=production
Rollback: vercel rollback + script de limpieza de ledger si datos corruptos
Revisión Adversarial (Sub-agente Opus)
✓ Plan aprobado — 14/14 checks superados
Completitud: todos los archivos afectados identificados
Orden de dependencias correcto (schema → servicio → UI/Stripe/Admin → wiring → launch)
Sin dependencias circulares en el grafo de pasos
Backward compatibility: legacy_unlimited preserva comportamiento actual
Rollback definido en pasos con riesgo de datos (1, 6, 7)
Tests en cada paso: unitarios, integración y e2e cubiertos
Idempotencia del webhook Stripe (anti-duplicados)
No hay pasos > 1 PR de tamaño (verificado por líneas de código estimadas)
Invariante de saldo no-negativo garantizado en DB (no solo en aplicación)
Feature flag para rollback rápido en producción
Monitoreo post-launch definido (PostHog + Sentry)
Contexto autocontenido: cada paso ejecutable por un agente fresco
RLS de Supabase cubierta (users solo ven su ledger)
Compensación de créditos si falla el LLM post-descuento