⚠ CRITICAL — 6 items, deploy bloqueado
Deben corregirse TODOS antes del deploy
| Estado | Check ID | Descripción del problema | Ubicación / Corrección |
|---|---|---|---|
| ✗ FAIL | SEC-01 |
API key de OpenAI hardcodeada en código fuente
La clave
sk-proj-abc123XYZ987realkey está expuesta en el repositorio. Cualquier persona con acceso al repo puede facturar a tu cuenta de OpenAI ilimitadamente. |
📄 src/lib/openai.ts:8
Mover a variable de entorno
OPENAI_API_KEY y revocar la clave actual en OpenAI dashboard. |
| ✗ FAIL | SEC-02 |
Ruta API de parcelas sin autenticación
El endpoint
/api/parcelas es accesible públicamente. Expone datos de todas las cooperativas registradas sin requerir sesión. |
📄 src/app/api/parcelas/route.ts:12
Añadir
getServerSession() al inicio del handler y retornar 401 si no hay sesión. |
| ✗ FAIL | SEC-18 |
Archivo .env incluido en el repositorio git
El archivo
.env con credenciales de Supabase, Stripe y OpenAI está siendo trackeado por git y podría subirse a GitHub. |
📄 .env (repo raíz)
Añadir
.env* a .gitignore. Ejecutar git rm --cached .env. |
| ✗ FAIL | DB-07 |
RLS no habilitado en tabla
cooperativasCualquier usuario autenticado puede leer y modificar datos de otras cooperativas. Los datos financieros y de NIF están completamente expuestos entre usuarios.
|
📄 supabase/migrations/001_init.sql
Añadir
ALTER TABLE cooperativas ENABLE ROW LEVEL SECURITY y política de acceso por auth.uid(). |
| ✗ FAIL | DB-07 |
RLS no habilitado en tabla
parcelasLas parcelas agrícolas (superficie, producción, coordenadas GPS) de todas las cooperativas son accesibles sin restricción por cualquier usuario de la plataforma.
|
📄 supabase/migrations/001_init.sql
Habilitar RLS y crear política
cooperativa_id = auth.uid() para SELECT, INSERT, UPDATE, DELETE. |
| ✗ FAIL | DB-03 |
SQL injection: query construida con template literal sin parametrizar
La variable
parcelaId se interpola directamente en la query SQL. Un atacante puede manipularla para extraer o modificar cualquier dato de la base. |
📄 src/utils/db.ts:45
Reemplazar por query parametrizada:
supabase.from('parcelas').select().eq('id', parcelaId). |
▼ HIGH — 8 items, corregir antes de ship
No bloquean el deploy pero deben resolverse este sprint
| Estado | Check ID | Descripción del problema | Ubicación / Corrección |
|---|---|---|---|
| △ FAIL | AI-04 |
Sin rate limiting en endpoint de chat IA
El endpoint
/api/chat que llama a GPT-4o no tiene ningún límite de peticiones. Un usuario malicioso puede generar facturas de miles de € en OpenAI. |
📄 src/app/api/chat/route.ts
Implementar rate limiting con
@upstash/ratelimit: máx. 10 req/min por usuario. |
| △ FAIL | CODE-01 |
14 sentencias
console.log en código de producciónLos logs de debug exponen datos internos (IDs de cooperativas, tokens de sesión) en la consola del navegador de usuarios finales.
|
📄 src/components/Dashboard.tsx (14 ocurrencias)
Eliminar o reemplazar con logger condicional. Añadir regla ESLint
no-console. |
| △ FAIL | CODE-03 |
Empty catch block en webhook de Stripe
Los errores en el procesamiento de pagos se silencian sin registrar. Si hay un fallo en un pago, no se notificará ni se registrará en ningún sistema de monitoreo.
|
📄 src/app/api/webhooks/stripe/route.ts:23
Añadir logging del error y notificación al sistema de monitoreo. Considerar Sentry.captureException(e).
|
| △ FAIL | DEP-04 |
3 vulnerabilidades críticas en npm audit
El lockfile actual contiene dependencias con CVEs conocidos. Ejecutar
npm audit muestra 3 critical en el árbol de dependencias. |
📄 package-lock.json
Ejecutar
npm audit fix o actualizar manualmente las dependencias afectadas. |
| ☐ MANUAL | DEPLOY-05 |
Sin plan de rollback documentado
No existe documentación sobre cómo revertir el deploy si algo falla. Para un SaaS con datos de clientes activos, el rollback debe estar planificado.
|
📄 Confirmar manualmente
Documentar procedimiento: snapshot de DB antes del deploy + URL de la versión anterior en Vercel.
|
| ☐ MANUAL | DEPLOY-06 |
Tests en staging no confirmados
No se ha confirmado que el entorno de staging con datos reales haya sido probado end-to-end (registro, alta de parcelas, pago con Stripe).
|
📄 Confirmar manualmente
Completar checklist de QA en staging antes de proceder.
|
| ☐ MANUAL | DB-01 |
Backups de base de datos no confirmados
Supabase tiene backups automáticos, pero no se ha verificado que estén activados en el proyecto de producción ni que el restore funcione.
|
📄 Verificar en Supabase dashboard
Activar point-in-time recovery. Probar restore en entorno de staging antes del go-live.
|
| △ FAIL | CODE-14 |
TypeScript strict mode desactivado
"strict": false en tsconfig permite errores de tipos silenciosos que pueden convertirse en bugs en producción, especialmente al manejar datos de la API de Supabase. |
📄 tsconfig.json
Activar
"strict": true y corregir los errores de tipos resultantes antes del deploy. |
ⓘ ADVISORY — 5 items, recomendados
No bloquean el deploy. Atender en el siguiente sprint
| Estado | Check ID | Descripción | Estado / Nota |
|---|---|---|---|
| ○ ADV | FE-01 |
Faltan meta tags OG (og:image, og:description)
El
layout.tsx tiene título pero carece de imagen OG y descripción. Perjudica el SEO y la apariencia al compartir en redes. |
📄 src/app/layout.tsx
|
| ○ ADV | FE-03 |
Falta página 404 personalizada
No existe
not-found.tsx. Las rutas inexistentes muestran la página genérica de Next.js sin branding de FarmTrack. |
📄 src/app/ (ausente)
|
| ✓ PASS | OBS-01 |
Monitoreo de errores configurado (Sentry)
Sentry está correctamente inicializado en
instrumentation.ts con DSN de producción. |
✓ Sentry activo
|
| ✓ PASS | DEPLOY-09 |
Health check endpoint configurado
El endpoint
/api/health existe y retorna 200 con estado de conexión a Supabase. |
✓ /api/health OK
|
| — SKIP | AI-06 |
Validación de inputs en servidor MCP
No aplicable: el proyecto no usa servidores MCP.
|
Stack no incluye MCP
|
🎯 Plan de corrección recomendado (orden de prioridad)
-
1Revocar y rotar la API key de OpenAI [SEC-01] Ir a platform.openai.com/api-keys, revocar
sk-proj-abc123XYZ987realkey, crear nueva clave y configurar como variable de entorno en Vercel. Tiempo estimado: 10 min. -
2Añadir .env a .gitignore + eliminar del historial [SEC-18] Ejecutar
echo '.env*' >> .gitignore && git rm --cached .env && git commit -m 'chore: remove .env from tracking'. Tiempo estimado: 5 min. -
3Habilitar RLS en tablas cooperativas y parcelas [DB-07 x2] Crear nueva migración con
ALTER TABLE cooperativas ENABLE ROW LEVEL SECURITYy políticas de acceso. Aplicar en staging primero. Tiempo estimado: 45 min. -
4Parametrizar query SQL vulnerable [DB-03] Reemplazar template literal en
src/utils/db.ts:45por query del cliente Supabase. Tiempo estimado: 15 min. -
5Añadir autenticación al endpoint /api/parcelas [SEC-02] Añadir
const session = await getServerSession(authOptions)al inicio del handler. Tiempo estimado: 20 min. -
6Rate limiting en /api/chat con Upstash [AI-04] Instalar
@upstash/ratelimit @upstash/redisy configurar límite de 10 req/min por usuario. Protege contra abuso de costes de OpenAI. Tiempo estimado: 30 min. -
7Resolver 3 CVEs críticos en dependencias [DEP-04] Ejecutar
npm audit fix --forcey validar que no se rompen tests existentes. Tiempo estimado: 20 min. -
8Limpiar console.log y corregir empty catch [CODE-01, CODE-03] Eliminar 14 console.log de Dashboard.tsx y añadir manejo de error en el webhook de Stripe. Tiempo estimado: 25 min.