1772 lines
49 KiB
Markdown
1772 lines
49 KiB
Markdown
# 🚀 PLAN DE IMPLEMENTACIÓN - MEJORAS DE LA APLICACIÓN
|
||
|
||
**Proyecto:** Guía TES Digital
|
||
**Fecha de Inicio:** 2025-01-07
|
||
**Versión del Plan:** 1.0.0
|
||
**Duración Total:** 20 semanas (~5 meses)
|
||
|
||
---
|
||
|
||
## 📊 RESUMEN EJECUTIVO (1 Página)
|
||
|
||
### Estado Actual del Proyecto
|
||
|
||
**Calificación General: 6.2/10** ⚠️ **BUENO CON MEJORAS NECESARIAS**
|
||
|
||
| Categoría | Calificación | Estado | Prioridad |
|
||
|-----------|--------------|--------|-----------|
|
||
| **Seguridad** | 5.1/10 | 🔴 Vulnerable | 🔴 Crítica |
|
||
| **Arquitectura** | 6.3/10 | ⚠️ Mejorable | 🟡 Media |
|
||
| **UX/UI Frontend** | 6.6/10 | ⚠️ Mejorable | 🟡 Media |
|
||
| **Modernización** | 6.5/10 | ⚠️ Desactualizado | 🟡 Media |
|
||
| **Limpieza de Código** | 6.0/10 | ⚠️ Necesita limpieza | 🟡 Media |
|
||
| **Medios/Assets** | 5.0/10 | 🔴 No optimizados | 🔴 Alta |
|
||
|
||
### Objetivos del Plan
|
||
|
||
**Objetivo Principal:** Convertir el proyecto de "BUENO con mejoras necesarias" a "EXCELENTE y escalable" en 20 semanas.
|
||
|
||
**Metas Específicas:**
|
||
1. ✅ **Seguridad:** Subir de 5.1/10 a 9.0/10 (eliminar vulnerabilidades críticas)
|
||
2. ✅ **Performance:** Optimizar assets (reducir 30MB → 4MB, -83%)
|
||
3. ✅ **Calidad:** Migrar backend a TypeScript (mejorar mantenibilidad)
|
||
4. ✅ **Modernización:** Actualizar React 18 → 19, Vite 5 → 7
|
||
5. ✅ **Limpieza:** Eliminar código muerto, assets no usados, dependencias obsoletas
|
||
6. ✅ **Testing:** Añadir suite de tests (objetivo: 60% cobertura)
|
||
|
||
### Recursos Estimados
|
||
|
||
| Fase | Duración | Esfuerzo (horas) | Prioridad | ROI |
|
||
|------|----------|------------------|-----------|-----|
|
||
| **Fase 1: Estabilización** | 4 semanas | 80-120h | 🔴 Alta | ⭐⭐⭐⭐⭐ |
|
||
| **Fase 2: Optimización** | 8 semanas | 160-240h | 🟡 Media | ⭐⭐⭐⭐ |
|
||
| **Fase 3: Escalabilidad** | 8 semanas | 160-240h | 🟢 Media | ⭐⭐⭐ |
|
||
| **Total** | **20 semanas** | **400-600h** | - | - |
|
||
|
||
### Riesgos y Mitigación
|
||
|
||
| Riesgo | Probabilidad | Impacto | Mitigación |
|
||
|--------|--------------|---------|------------|
|
||
| **Breaking changes en migraciones** | Media | Alto | Feature flags, tests incrementales |
|
||
| **Tiempo subestimado** | Alta | Medio | Buffer 20% en cada fase |
|
||
| **Regresiones** | Media | Alto | Tests automatizados antes de cada release |
|
||
| **Conflicto con features nuevas** | Baja | Medio | Priorizar estabilidad sobre features |
|
||
|
||
---
|
||
|
||
## 🗓️ HOJA DE RUTA VISUAL (Timeline)
|
||
|
||
```
|
||
SEMANA │ 1 2 3 4 │ 5 6 7 8 9 10 11 12 │ 13 14 15 16 17 18 19 20 │
|
||
──────────┼──────────────────────────────────────────────────────────────────┤
|
||
FASE 1: │██████████████████████████████████████████████████████████████████│
|
||
ESTAB. │ Seguridad │ Limpieza │ Tests │ Backend TS │ │
|
||
──────────┼──────────────────────────────────────────────────────────────────┤
|
||
FASE 2: │ │████████████████████████████████████████████████████│
|
||
OPTIMIZ. │ │ React 19 │ Vite 7 │ Assets │ UX │ Dependencias │
|
||
──────────┼──────────────────────────────────────────────────────────────────┤
|
||
FASE 3: │ │ │████████████████████████████████│
|
||
ESCALAB. │ │ │ Cache │ Monitoring │ Cloud │
|
||
──────────┼──────────────────────────────────────────────────────────────────┤
|
||
MILESTONE │ 🔒 Seguro │ ⚡ Optimizado │ 📈 Escalable │
|
||
```
|
||
|
||
**Hitos Clave:**
|
||
- **Semana 4:** ✅ Seguridad crítica resuelta
|
||
- **Semana 8:** ✅ Backend migrado a TypeScript
|
||
- **Semana 12:** ✅ Stack actualizado, assets optimizados
|
||
- **Semana 20:** ✅ Proyecto escalable y monitoreado
|
||
|
||
---
|
||
|
||
## ✅ ESTADO ACTUAL (2026-01-19)
|
||
|
||
### Pendientes prioritarios para continuar el plan
|
||
|
||
**Fase 1 – Seguridad (Semana 1):**
|
||
- [ ] Validación de `JWT_SECRET` en startup
|
||
- [ ] Rate limiting en endpoints críticos
|
||
- [ ] Security headers (Helmet)
|
||
- [ ] CORS restringido en producción
|
||
- [ ] Validación de inputs (Zod) en backend
|
||
- [ ] Sanitización HTML/texto y fix XSS en `MarkdownViewer`
|
||
- [ ] Verificación HMAC en `webhook-deploy.sh`
|
||
- [ ] Validación de variables de entorno en backend
|
||
|
||
**Fase 1 – Limpieza (Semana 2):**
|
||
- [ ] Optimización de imágenes grandes (WebP + PNG comprimido)
|
||
- [ ] Renombrado de archivos con espacios y actualización de referencias
|
||
- [ ] Eliminación de carpetas vacías
|
||
- [ ] Verificación de referencias rotas en guías
|
||
- [ ] Depuración de dependencias no usadas (depcheck)
|
||
- [ ] Consolidación de scripts duplicados
|
||
- [ ] Detección y eliminación de código muerto (ts-prune/unimported)
|
||
|
||
**Fase 1 – Tests (Semana 3):**
|
||
- [ ] Definir stack de tests definitivo (Jest vs Vitest) y configurar scripts
|
||
- [ ] Cobertura mínima 20% con tests de componentes/servicios/hooks críticos
|
||
|
||
**Fase 1 – Backend TS (Semana 4):**
|
||
- [ ] Completar migración TypeScript en backend (rutas y servicios)
|
||
- [ ] Revisar scripts de build y arranque en producción
|
||
|
||
**Operación / Deploy:**
|
||
- [ ] Actualizar Node.js del servidor a >= 20.19 para compatibilidad con Vite 7
|
||
- [ ] Corregir hook `post-receive` (reset con `--work-tree`) para evitar fallos de despliegue
|
||
|
||
**Contenido clínico pendiente (alto impacto):**
|
||
- [ ] Completar 8 capítulos placeholder del manual
|
||
- [ ] Añadir cálculo rápido de Naloxona en checklist de Intoxicaciones
|
||
- [ ] Añadir guía rápida de peso RN en checklist de Parto
|
||
|
||
---
|
||
|
||
## 📋 FASE 1: ESTABILIZACIÓN (Semanas 1-4)
|
||
|
||
### Objetivo de la Fase
|
||
**Hacer el proyecto seguro, estable y testeable**
|
||
|
||
**Duración:** 4 semanas
|
||
**Esfuerzo:** 80-120 horas
|
||
**Prioridad:** 🔴 ALTA
|
||
**ROI:** ⭐⭐⭐⭐⭐ (Muy Alto)
|
||
|
||
---
|
||
|
||
### Semana 1: Seguridad Crítica (20-30 horas)
|
||
|
||
#### 🔴 Día 1-2: Fixes de Seguridad Inmediatos
|
||
|
||
**Objetivo:** Eliminar vulnerabilidades críticas
|
||
|
||
**Tareas:**
|
||
- [ ] **JWT Secret Validation** (2 horas)
|
||
- Ubicación: `backend/src/routes/auth.js:11`
|
||
- Validar `JWT_SECRET` en startup (no usar fallback débil)
|
||
- Generar secret seguro: `openssl rand -base64 32`
|
||
|
||
```javascript
|
||
// backend/src/config/security.js (NUEVO)
|
||
import dotenv from 'dotenv';
|
||
dotenv.config();
|
||
|
||
export function validateSecurityConfig() {
|
||
const JWT_SECRET = process.env.JWT_SECRET;
|
||
if (!JWT_SECRET || JWT_SECRET === 'emerges-tes-secret-key-change-in-production') {
|
||
console.error('❌ CRÍTICO: JWT_SECRET no configurado');
|
||
console.error(' Generar con: openssl rand -base64 32');
|
||
process.exit(1);
|
||
}
|
||
|
||
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
|
||
if (!WEBHOOK_SECRET && process.env.NODE_ENV === 'production') {
|
||
console.error('❌ CRÍTICO: WEBHOOK_SECRET no configurado en producción');
|
||
process.exit(1);
|
||
}
|
||
|
||
return { JWT_SECRET, WEBHOOK_SECRET };
|
||
}
|
||
```
|
||
|
||
- [ ] **Rate Limiting** (3 horas)
|
||
- Ubicación: `backend/src/index.js`
|
||
- Instalar: `npm install express-rate-limit`
|
||
- Configurar rate limiters por endpoint
|
||
|
||
```javascript
|
||
// backend/src/middleware/rate-limit.js (NUEVO)
|
||
import rateLimit from 'express-rate-limit';
|
||
|
||
// General API limiter
|
||
export const generalLimiter = rateLimit({
|
||
windowMs: 15 * 60 * 1000, // 15 minutos
|
||
max: 100, // 100 requests por IP
|
||
message: 'Demasiadas peticiones desde esta IP, intenta en 15 minutos',
|
||
standardHeaders: true,
|
||
legacyHeaders: false,
|
||
});
|
||
|
||
// Auth endpoints (más estricto)
|
||
export const authLimiter = rateLimit({
|
||
windowMs: 15 * 60 * 1000,
|
||
max: 5, // 5 intentos de login por IP
|
||
message: 'Demasiados intentos de login, intenta en 15 minutos',
|
||
skipSuccessfulRequests: true,
|
||
});
|
||
|
||
// Content creation (medio)
|
||
export const contentWriteLimiter = rateLimit({
|
||
windowMs: 60 * 60 * 1000, // 1 hora
|
||
max: 20, // 20 creaciones por hora
|
||
message: 'Límite de creación de contenido alcanzado, intenta en 1 hora',
|
||
});
|
||
```
|
||
|
||
- [ ] **Helmet.js Headers** (2 horas)
|
||
- Instalar: `npm install helmet`
|
||
- Configurar headers de seguridad
|
||
|
||
```javascript
|
||
// backend/src/middleware/security-headers.js (NUEVO)
|
||
import helmet from 'helmet';
|
||
|
||
export const securityHeaders = helmet({
|
||
contentSecurityPolicy: {
|
||
directives: {
|
||
defaultSrc: ["'self'"],
|
||
styleSrc: ["'self'", "'unsafe-inline'"],
|
||
scriptSrc: ["'self'"],
|
||
imgSrc: ["'self'", "data:", "https:"],
|
||
connectSrc: ["'self'"],
|
||
fontSrc: ["'self'"],
|
||
objectSrc: ["'none'"],
|
||
mediaSrc: ["'self'"],
|
||
frameSrc: ["'none'"],
|
||
},
|
||
},
|
||
hsts: {
|
||
maxAge: 31536000, // 1 año
|
||
includeSubDomains: true,
|
||
preload: true,
|
||
},
|
||
crossOriginEmbedderPolicy: false, // Para compatibilidad
|
||
crossOriginResourcePolicy: { policy: "cross-origin" }, // Para assets
|
||
});
|
||
```
|
||
|
||
- [ ] **CORS Fix** (1 hora)
|
||
- Ubicación: `backend/src/index.js`
|
||
- Limitar orígenes incluso en desarrollo
|
||
|
||
```javascript
|
||
// backend/src/config/cors.js (NUEVO)
|
||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||
const defaultDevOrigins = ['http://localhost:8096', 'http://localhost:5174'];
|
||
const allowedOrigins = process.env.CORS_ORIGINS
|
||
? process.env.CORS_ORIGINS.split(',')
|
||
: (isDevelopment ? defaultDevOrigins : []);
|
||
|
||
if (!isDevelopment && allowedOrigins.length === 0) {
|
||
console.error('❌ CRÍTICO: CORS_ORIGINS no configurado en producción');
|
||
process.exit(1);
|
||
}
|
||
|
||
export const corsConfig = {
|
||
origin: (origin, callback) => {
|
||
if (!origin || allowedOrigins.includes(origin)) {
|
||
callback(null, true);
|
||
} else {
|
||
callback(new Error('Origen no permitido por CORS'));
|
||
}
|
||
},
|
||
credentials: true,
|
||
optionsSuccessStatus: 200,
|
||
};
|
||
```
|
||
|
||
**Deliverables:**
|
||
- ✅ Validación de secrets en startup
|
||
- ✅ Rate limiting implementado
|
||
- ✅ Security headers configurados
|
||
- ✅ CORS restringido
|
||
|
||
**Checklist de Verificación:**
|
||
- [ ] App no arranca sin `JWT_SECRET` configurado
|
||
- [ ] Rate limiting activo en `/api/auth/login`
|
||
- [ ] Headers de seguridad presentes en respuestas
|
||
- [ ] CORS solo permite orígenes configurados
|
||
|
||
---
|
||
|
||
#### 🔴 Día 3-4: Validación de Inputs
|
||
|
||
**Objetivo:** Prevenir inyecciones SQL y XSS
|
||
|
||
**Tareas:**
|
||
- [ ] **Validación con Zod** (6 horas)
|
||
- Crear schemas de validación para todos los endpoints
|
||
- Ubicación: `backend/src/validators/` (NUEVO)
|
||
|
||
```javascript
|
||
// backend/src/validators/content.js (NUEVO)
|
||
import { z } from 'zod';
|
||
|
||
export const createContentSchema = z.object({
|
||
id: z.string().min(1).max(100).regex(/^[a-z0-9-]+$/),
|
||
type: z.enum(['protocol', 'guide', 'manual', 'checklist']),
|
||
title: z.string().min(1).max(500),
|
||
content: z.record(z.any()), // JSONB
|
||
priority: z.enum(['critica', 'alta', 'media', 'baja']).optional(),
|
||
category: z.string().max(100).optional(),
|
||
});
|
||
|
||
export const updateContentSchema = createContentSchema.partial();
|
||
```
|
||
|
||
- [ ] **Sanitización de Inputs** (3 horas)
|
||
- Instalar: `npm install dompurify jsdom`
|
||
- Sanitizar contenido HTML en frontend
|
||
|
||
```typescript
|
||
// src/utils/sanitize.ts (NUEVO)
|
||
import DOMPurify from 'dompurify';
|
||
import { JSDOM } from 'jsdom';
|
||
|
||
const window = new JSDOM('').window;
|
||
const purify = DOMPurify(window as any);
|
||
|
||
export function sanitizeHTML(html: string): string {
|
||
return purify.sanitize(html, {
|
||
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li', 'h1', 'h2', 'h3'],
|
||
ALLOWED_ATTR: [],
|
||
});
|
||
}
|
||
|
||
export function sanitizeText(text: string): string {
|
||
return text
|
||
.replace(/[<>]/g, '') // Eliminar < >
|
||
.replace(/javascript:/gi, '') // Eliminar javascript:
|
||
.trim();
|
||
}
|
||
```
|
||
|
||
- [ ] **Fix XSS en MarkdownViewer** (2 horas)
|
||
- Ubicación: `src/components/content/MarkdownViewer.tsx:278`
|
||
- Usar `sanitizeHTML` para contenido HTML
|
||
|
||
```typescript
|
||
// src/components/content/MarkdownViewer.tsx
|
||
import { sanitizeHTML } from '@/utils/sanitize';
|
||
|
||
img: ({ node, src, alt, ...props }: any) => {
|
||
// Sanitizar src y alt
|
||
const safeSrc = sanitizeText(src || '');
|
||
const safeAlt = sanitizeText(alt || '');
|
||
|
||
return (
|
||
<img
|
||
{...props}
|
||
src={safeSrc}
|
||
alt={safeAlt}
|
||
loading="lazy"
|
||
decoding="async"
|
||
className="max-w-full h-auto rounded-lg my-4"
|
||
/>
|
||
);
|
||
}
|
||
```
|
||
|
||
**Deliverables:**
|
||
- ✅ Validación Zod en todos los endpoints
|
||
- ✅ Sanitización de inputs en frontend
|
||
- ✅ XSS fixes en componentes críticos
|
||
|
||
---
|
||
|
||
#### 🔴 Día 5: Webhook Security y Environment Variables
|
||
|
||
**Objetivo:** Asegurar scripts de deploy
|
||
|
||
**Tareas:**
|
||
- [ ] **Webhook HMAC Verification** (4 horas)
|
||
- Ubicación: `webhook-deploy.sh:10`
|
||
- Verificar HMAC signature de GitHub
|
||
|
||
```bash
|
||
# webhook-deploy.sh (ACTUALIZAR)
|
||
#!/bin/bash
|
||
|
||
WEBHOOK_SECRET="${WEBHOOK_SECRET}"
|
||
if [ -z "$WEBHOOK_SECRET" ]; then
|
||
echo "ERROR: WEBHOOK_SECRET no configurado"
|
||
exit 1
|
||
fi
|
||
|
||
# Leer payload y signature
|
||
PAYLOAD=$(cat)
|
||
SIGNATURE=$(echo "$PAYLOAD" | jq -r '.headers["X-Hub-Signature-256"]' 2>/dev/null || echo '')
|
||
|
||
if [ -z "$SIGNATURE" ]; then
|
||
echo "ERROR: Firma HMAC no encontrada"
|
||
exit 1
|
||
fi
|
||
|
||
# Verificar HMAC
|
||
EXPECTED_SIGNATURE="sha256=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | cut -d' ' -f2)"
|
||
|
||
if [ "$SIGNATURE" != "$EXPECTED_SIGNATURE" ]; then
|
||
echo "ERROR: Firma HMAC inválida"
|
||
exit 1
|
||
fi
|
||
|
||
# Proceder con deploy...
|
||
```
|
||
|
||
- [ ] **Environment Variables Validation** (2 horas)
|
||
- Crear script de validación al startup
|
||
|
||
```javascript
|
||
// backend/src/config/env.js (NUEVO)
|
||
import dotenv from 'dotenv';
|
||
dotenv.config();
|
||
|
||
const requiredEnvVars = [
|
||
'DB_HOST',
|
||
'DB_NAME',
|
||
'DB_USER',
|
||
'DB_PASSWORD',
|
||
'JWT_SECRET',
|
||
];
|
||
|
||
export function validateEnv() {
|
||
const missing = requiredEnvVars.filter(key => !process.env[key]);
|
||
|
||
if (missing.length > 0) {
|
||
console.error('❌ CRÍTICO: Variables de entorno faltantes:');
|
||
missing.forEach(key => console.error(` - ${key}`));
|
||
process.exit(1);
|
||
}
|
||
|
||
// Validar formatos
|
||
if (process.env.JWT_SECRET && process.env.JWT_SECRET.length < 32) {
|
||
console.error('❌ CRÍTICO: JWT_SECRET debe tener al menos 32 caracteres');
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log('✅ Variables de entorno validadas correctamente');
|
||
}
|
||
```
|
||
|
||
**Deliverables:**
|
||
- ✅ Webhook con verificación HMAC
|
||
- ✅ Validación de env vars en startup
|
||
|
||
---
|
||
|
||
### Semana 2: Limpieza de Código y Assets (20-30 horas)
|
||
|
||
#### 🟡 Día 1-2: Limpieza de Assets
|
||
|
||
**Objetivo:** Optimizar medios y eliminar duplicados
|
||
|
||
**Tareas:**
|
||
- [ ] **Eliminar dist/assets/** (5 min)
|
||
```bash
|
||
rm -rf dist/assets/
|
||
# Verificar que dist/ está en .gitignore
|
||
```
|
||
|
||
- [ ] **Optimizar Imágenes Grandes** (6 horas)
|
||
- Instalar herramientas: `sudo apt-get install imagemagick webp pngquant`
|
||
- Optimizar 3 imágenes >5MB en `assets/images/bloque_00/`
|
||
|
||
```bash
|
||
# scripts/optimize-images.sh (CREAR)
|
||
#!/bin/bash
|
||
SRC_DIR="assets/images/bloque_00"
|
||
DEST_DIR="public/assets/infografias/bloque-0-fundamentos"
|
||
|
||
mkdir -p "$DEST_DIR"
|
||
|
||
for img in "$SRC_DIR"/*.png; do
|
||
if [ -f "$img" ]; then
|
||
filename=$(basename "$img" .png)
|
||
clean_name=$(echo "$filename" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -d ':' | sed 's/[^a-z0-9-]//g')
|
||
|
||
# Convertir a WebP (85% calidad, max 1920px)
|
||
convert "$img" -resize 1920x1920> -quality 85 "$DEST_DIR/$clean_name.webp <!-- PLACEHOLDER: No requiere creación -->"
|
||
|
||
# PNG optimizado como fallback
|
||
pngquant --quality=65-80 "$img" --output "$DEST_DIR/$clean_name_optimized.png" || \
|
||
convert "$img" -resize 1920x1920> -quality 85 "$DEST_DIR/$clean_name_optimized.png"
|
||
|
||
echo "✅ Optimizado: $filename -> $clean_name.webp"
|
||
fi
|
||
done
|
||
|
||
echo "📊 Espacio recuperado: ~15 MB"
|
||
```
|
||
|
||
- [ ] **Renombrar Archivos con Espacios** (2 horas)
|
||
- Renombrar 4 archivos con espacios
|
||
|
||
```bash
|
||
# scripts/fix-asset-names.sh (CREAR)
|
||
find public/assets -type f -name "* *" | while read file; do
|
||
newname=$(echo "$file" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed 's/[^a-z0-9-._\/]//g')
|
||
if [ "$file" != "$newname" ]; then
|
||
mv "$file" "$newname"
|
||
echo "✅ Renombrado: $(basename "$file") -> $(basename "$newname")"
|
||
echo "⚠️ Actualizar referencias en código"
|
||
fi
|
||
done
|
||
```
|
||
|
||
- [ ] **Eliminar Carpetas Vacías** (30 min)
|
||
```bash
|
||
find assets public/assets -type d -empty -not -path "./.git/*" -delete
|
||
```
|
||
|
||
- [ ] **Verificar Referencias Rotas** (2 horas)
|
||
- Verificar imágenes referenciadas en `guia-refuerzo-rcp-adulto-svb.json` que no existen
|
||
- Añadir placeholders o eliminar referencias
|
||
|
||
**Deliverables:**
|
||
- ✅ ~30 MB de espacio recuperado
|
||
- ✅ Imágenes optimizadas (WebP + PNG comprimido)
|
||
- ✅ Archivos renombrados sin espacios
|
||
- ✅ Referencias actualizadas
|
||
|
||
---
|
||
|
||
#### 🟡 Día 3-4: Limpieza de Código
|
||
|
||
**Objetivo:** Eliminar código muerto y archivos innecesarios
|
||
|
||
**Tareas:**
|
||
- [ ] **Ejecutar depcheck** (1 hora)
|
||
```bash
|
||
# Frontend
|
||
npx depcheck --ignores="@types/*,eslint-*,typescript-*,@vitejs/*,vite"
|
||
|
||
# Backend
|
||
cd backend && npx depcheck
|
||
```
|
||
|
||
- [ ] **Eliminar Dependencias No Usadas** (2 horas)
|
||
- Eliminar dependencias confirmadas no usadas
|
||
- Actualizar `package.json`
|
||
|
||
- [ ] **Eliminar Archivos .backup** (30 min)
|
||
```bash
|
||
find . -name "*.backup" -not -path "./node_modules/*" -delete
|
||
```
|
||
|
||
- [ ] **Eliminar Scripts Duplicados** (2 horas)
|
||
- Consolidar `cleanup_completo.sh` y `cleanup_project.sh`
|
||
- Consolidar `deploy.sh`, `desplegar.sh`, `docker.sh`
|
||
- Documentar diferencias si todas son necesarias
|
||
|
||
- [ ] **Detectar Código Muerto** (3 horas)
|
||
```bash
|
||
# Detectar exports no usados
|
||
npx ts-prune | head -50
|
||
|
||
# Detectar imports no usados
|
||
npx unimported
|
||
```
|
||
|
||
**Deliverables:**
|
||
- ✅ Dependencias no usadas eliminadas
|
||
- ✅ Archivos de backup eliminados
|
||
- ✅ Scripts consolidados
|
||
- ✅ Código muerto identificado y eliminado
|
||
|
||
---
|
||
|
||
### Semana 3: Test Suite Básico (20-30 horas)
|
||
|
||
#### 🟡 Día 1-3: Setup de Testing
|
||
|
||
**Objetivo:** Implementar infraestructura de tests
|
||
|
||
**Tareas:**
|
||
- [ ] **Configurar Jest + React Testing Library** (4 horas)
|
||
- Instalar: `npm install --save-dev jest @testing-library/react @testing-library/jest-dom @testing-library/user-event jest-environment-jsdom`
|
||
|
||
```json
|
||
// package.json (ACTUALIZAR)
|
||
{
|
||
"scripts": {
|
||
"test": "jest",
|
||
"test:watch": "jest --watch",
|
||
"test:coverage": "jest --coverage"
|
||
},
|
||
"jest": {
|
||
"testEnvironment": "jsdom",
|
||
"setupFilesAfterEnv": ["<rootDir>/src/test/setup.ts"],
|
||
"moduleNameMapper": {
|
||
"^@/(.*)$": "<rootDir>/src/$1"
|
||
},
|
||
"collectCoverageFrom": [
|
||
"src/**/*.{ts,tsx}",
|
||
"!src/**/*.d.ts",
|
||
"!src/main.tsx",
|
||
"!src/vite-env.d.ts"
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
```typescript
|
||
// src/test/setup.ts (CREAR)
|
||
import '@testing-library/jest-dom';
|
||
import { expect, afterEach } from 'vitest';
|
||
import { cleanup } from '@testing-library/react';
|
||
|
||
afterEach(() => {
|
||
cleanup();
|
||
});
|
||
```
|
||
|
||
- [ ] **Tests de Componentes Críticos** (8 horas)
|
||
- `ErrorBoundary.test.tsx`
|
||
- `MarkdownViewer.test.tsx`
|
||
- `ContentAdapter.test.ts`
|
||
- `ProcedureCard.test.tsx`
|
||
|
||
```typescript
|
||
// src/components/ErrorBoundary.test.tsx (CREAR)
|
||
import { render, screen } from '@testing-library/react';
|
||
import ErrorBoundary from './ErrorBoundary';
|
||
|
||
describe('ErrorBoundary', () => {
|
||
it('should render children when no error', () => {
|
||
render(
|
||
<ErrorBoundary>
|
||
<div>Test Content</div>
|
||
</ErrorBoundary>
|
||
);
|
||
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
||
});
|
||
|
||
it('should render error UI when error occurs', () => {
|
||
const ThrowError = () => {
|
||
throw new Error('Test error');
|
||
};
|
||
|
||
render(
|
||
<ErrorBoundary>
|
||
<ThrowError />
|
||
</ErrorBoundary>
|
||
);
|
||
|
||
expect(screen.getByText(/Error al cargar/i)).toBeInTheDocument();
|
||
});
|
||
});
|
||
```
|
||
|
||
- [ ] **Tests de Servicios** (4 horas)
|
||
- `content-adapter.test.ts`
|
||
- `indexeddb.test.ts`
|
||
|
||
```typescript
|
||
// src/services/content-adapter.test.ts (CREAR)
|
||
import { describe, it, expect, beforeEach } from 'vitest';
|
||
import { ContentAdapterFactory } from './content-adapter';
|
||
|
||
describe('ContentAdapterFactory', () => {
|
||
beforeEach(() => {
|
||
// Reset localStorage
|
||
localStorage.clear();
|
||
});
|
||
|
||
it('should create LocalContentAdapter by default', () => {
|
||
const adapter = ContentAdapterFactory.create();
|
||
expect(adapter).toBeDefined();
|
||
expect(adapter.constructor.name).toBe('LocalContentAdapter');
|
||
});
|
||
|
||
it('should create ExternalContentAdapter when API_URL is set', () => {
|
||
process.env.VITE_API_URL = 'http://localhost:3000';
|
||
const adapter = ContentAdapterFactory.create();
|
||
expect(adapter.constructor.name).toBe('ExternalContentAdapter');
|
||
delete process.env.VITE_API_URL;
|
||
});
|
||
});
|
||
```
|
||
|
||
- [ ] **Tests de Hooks** (4 horas)
|
||
- `useFavorites.test.ts`
|
||
- `useSearchHistory.test.ts`
|
||
- `usePWAInstall.test.ts`
|
||
|
||
**Deliverables:**
|
||
- ✅ Jest configurado
|
||
- ✅ Tests de componentes críticos (objetivo: 10 tests)
|
||
- ✅ Tests de servicios (objetivo: 5 tests)
|
||
- ✅ Tests de hooks (objetivo: 5 tests)
|
||
- ✅ Cobertura objetivo: 20% (mínimo inicial)
|
||
|
||
---
|
||
|
||
### Semana 4: Backend TypeScript - Parte 1 (20-30 horas)
|
||
|
||
#### 🟡 Día 1-3: Migración Inicial
|
||
|
||
**Objetivo:** Configurar TypeScript en backend
|
||
|
||
**Tareas:**
|
||
- [ ] **Configurar TypeScript** (3 horas)
|
||
- Instalar: `npm install --save-dev typescript @types/node @types/express @types/pg @types/bcrypt @types/jsonwebtoken`
|
||
- Crear `backend/tsconfig.json`
|
||
|
||
```json
|
||
// backend/tsconfig.json (CREAR)
|
||
{
|
||
"compilerOptions": {
|
||
"target": "ES2020",
|
||
"module": "ES2020",
|
||
"lib": ["ES2020"],
|
||
"moduleResolution": "node",
|
||
"rootDir": "./src",
|
||
"outDir": "./dist",
|
||
"strict": true,
|
||
"esModuleInterop": true,
|
||
"skipLibCheck": true,
|
||
"forceConsistentCasingInFileNames": true,
|
||
"resolveJsonModule": true,
|
||
"allowSyntheticDefaultImports": true,
|
||
"declaration": true,
|
||
"declarationMap": true,
|
||
"sourceMap": true,
|
||
"noUnusedLocals": true,
|
||
"noUnusedParameters": true,
|
||
"noImplicitReturns": true,
|
||
"noFallthroughCasesInSwitch": true
|
||
},
|
||
"include": ["src/**/*"],
|
||
"exclude": ["node_modules", "dist"]
|
||
}
|
||
```
|
||
|
||
- [ ] **Migrar Config y Database** (4 horas)
|
||
- Renombrar: `config/database.js` → `config/database.ts`
|
||
- Añadir tipos a Pool y queries
|
||
|
||
```typescript
|
||
// backend/config/database.ts (MIGRAR)
|
||
import pg from 'pg';
|
||
import dotenv from 'dotenv';
|
||
|
||
dotenv.config();
|
||
|
||
const { Pool } = pg;
|
||
|
||
export const pool = new Pool({
|
||
host: process.env.DB_HOST || 'localhost',
|
||
port: parseInt(process.env.DB_PORT || '5432', 10),
|
||
database: process.env.DB_NAME || 'emerges_tes',
|
||
user: process.env.DB_USER || 'postgres',
|
||
password: process.env.DB_PASSWORD || '',
|
||
max: 20,
|
||
idleTimeoutMillis: 30000,
|
||
connectionTimeoutMillis: 2000,
|
||
});
|
||
|
||
export async function query(text: string, params?: any[]): Promise<pg.QueryResult> {
|
||
return await pool.query(text, params);
|
||
}
|
||
|
||
export async function testConnection(): Promise<boolean> {
|
||
try {
|
||
const result = await query('SELECT NOW()');
|
||
console.log('✅ Conexión a PostgreSQL exitosa:', result.rows[0].now);
|
||
return true;
|
||
} catch (error) {
|
||
console.error('❌ Error conectando a PostgreSQL:', (error as Error).message);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
export async function closePool(): Promise<void> {
|
||
await pool.end();
|
||
}
|
||
```
|
||
|
||
- [ ] **Migrar Middleware** (3 horas)
|
||
- Renombrar: `middleware/auth.js` → `middleware/auth.ts`
|
||
- Añadir tipos a funciones de autenticación
|
||
|
||
```typescript
|
||
// backend/src/middleware/auth.ts (MIGRAR)
|
||
import { Request, Response, NextFunction } from 'express';
|
||
import jwt from 'jsonwebtoken';
|
||
import { query } from '../../config/database.js';
|
||
import { validateSecurityConfig } from '../config/security.js';
|
||
|
||
const { JWT_SECRET } = validateSecurityConfig();
|
||
|
||
export interface AuthRequest extends Request {
|
||
user?: {
|
||
id: string;
|
||
username: string;
|
||
role: string;
|
||
};
|
||
}
|
||
|
||
export async function authenticate(
|
||
req: AuthRequest,
|
||
res: Response,
|
||
next: NextFunction
|
||
): Promise<void> {
|
||
try {
|
||
const token = req.headers.authorization?.replace('Bearer ', '');
|
||
|
||
if (!token) {
|
||
res.status(401).json({ error: 'Token de autenticación requerido' });
|
||
return;
|
||
}
|
||
|
||
const decoded = jwt.verify(token, JWT_SECRET) as { userId: string };
|
||
const result = await query(
|
||
'SELECT id, username, role FROM emerges_content.users WHERE id = $1',
|
||
[decoded.userId]
|
||
);
|
||
|
||
if (result.rows.length === 0) {
|
||
res.status(401).json({ error: 'Usuario no encontrado' });
|
||
return;
|
||
}
|
||
|
||
req.user = result.rows[0];
|
||
next();
|
||
} catch (error) {
|
||
res.status(401).json({ error: 'Token inválido' });
|
||
}
|
||
}
|
||
|
||
export function requirePermission(permission: string) {
|
||
return (req: AuthRequest, res: Response, next: NextFunction): void => {
|
||
if (!req.user) {
|
||
res.status(401).json({ error: 'No autenticado' });
|
||
return;
|
||
}
|
||
|
||
// Lógica de permisos (simplificada)
|
||
if (req.user.role === 'super_admin') {
|
||
next();
|
||
return;
|
||
}
|
||
|
||
// Verificar permisos específicos según role
|
||
// TODO: Implementar sistema de permisos completo
|
||
|
||
next();
|
||
};
|
||
}
|
||
```
|
||
|
||
- [ ] **Actualizar Scripts de Build** (2 horas)
|
||
- Actualizar `package.json` scripts para compilar TypeScript
|
||
|
||
```json
|
||
// backend/package.json (ACTUALIZAR)
|
||
{
|
||
"scripts": {
|
||
"build": "tsc",
|
||
"dev": "tsc --watch",
|
||
"start": "node dist/index.js",
|
||
"start:dev": "tsx src/index.js"
|
||
},
|
||
"devDependencies": {
|
||
"tsx": "^4.7.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Deliverables:**
|
||
- ✅ TypeScript configurado en backend
|
||
- ✅ Config y Database migrados
|
||
- ✅ Middleware migrado
|
||
- ✅ Scripts de build actualizados
|
||
|
||
---
|
||
|
||
#### 🟡 Día 4-5: Migración de Rutas - Parte 1
|
||
|
||
**Objetivo:** Migrar rutas críticas a TypeScript
|
||
|
||
**Tareas:**
|
||
- [ ] **Migrar auth.js** (4 horas)
|
||
- Renombrar: `routes/auth.js` → `routes/auth.ts`
|
||
- Añadir tipos a todas las funciones
|
||
|
||
- [ ] **Migrar content.js** (6 horas)
|
||
- Renombrar: `routes/content.js` → `routes/content.ts`
|
||
- Añadir tipos a queries y responses
|
||
|
||
- [ ] **Migrar content-pack.js** (3 horas)
|
||
- Renombrar: `routes/content-pack.js` → `routes/content-pack.ts`
|
||
|
||
**Deliverables:**
|
||
- ✅ 3 rutas principales migradas a TypeScript
|
||
- ✅ Tipos añadidos a funciones críticas
|
||
|
||
---
|
||
|
||
**🎯 MILESTONE SEMANA 4:** Backend parcialmente migrado a TypeScript (50%)
|
||
|
||
---
|
||
|
||
## 📋 FASE 2: OPTIMIZACIÓN (Semanas 5-12)
|
||
|
||
### Objetivo de la Fase
|
||
**Optimizar performance, actualizar stack y mejorar UX**
|
||
|
||
**Duración:** 8 semanas
|
||
**Esfuerzo:** 160-240 horas
|
||
**Prioridad:** 🟡 MEDIA
|
||
**ROI:** ⭐⭐⭐⭐ (Alto)
|
||
|
||
---
|
||
|
||
### Semana 5-6: Backend TypeScript - Parte 2 (40-60 horas)
|
||
|
||
#### Continuación de Migración
|
||
|
||
**Tareas:**
|
||
- [ ] Migrar rutas restantes (`drugs.js`, `stats.js`, `media.js`, etc.)
|
||
- [ ] Migrar servicios (`pack-generator.js`, `scorm-generator.js`)
|
||
- [ ] Migrar utils (si existen)
|
||
- [ ] Actualizar todos los scripts en `backend/scripts/`
|
||
|
||
**Deliverables:**
|
||
- ✅ Backend 100% TypeScript
|
||
- ✅ Type safety completo
|
||
- ✅ Mejor autocomplete en IDE
|
||
|
||
---
|
||
|
||
### Semana 7-8: React 18 → 19 (40-60 horas)
|
||
|
||
#### Actualización de React
|
||
|
||
**Tareas:**
|
||
- [ ] Actualizar React y React DOM a 19.2.3
|
||
- [ ] Actualizar `@types/react` y `@types/react-dom`
|
||
- [ ] Verificar compatibilidad Radix UI
|
||
- [ ] Actualizar código que use APIs deprecated
|
||
- [ ] Implementar nuevas APIs (metadata, forms) donde aplicable
|
||
- [ ] Testing exhaustivo de componentes
|
||
|
||
**Deliverables:**
|
||
- ✅ React 19 funcionando
|
||
- ✅ Nuevas APIs implementadas
|
||
- ✅ Tests pasando
|
||
|
||
---
|
||
|
||
### ✅ Semana 9-10: Vite 5 → 7 - **COMPLETADA** (2026-01-11)
|
||
|
||
#### Actualización de Vite
|
||
|
||
**Tareas:**
|
||
- ✅ Actualizar Vite a 7.3.1
|
||
- ✅ Actualizar `@vitejs/plugin-react-swc` a 4.2.2
|
||
- ✅ Actualizar Vitest a 4.0.17
|
||
- ✅ Refactorizar plugins personalizados (compatibles con Vite 7)
|
||
- ✅ Actualizar `vite.config.ts` (añadido dompurify a clasificación)
|
||
- ✅ Verificar code splitting funciona correctamente
|
||
|
||
**Deliverables:**
|
||
- ✅ Vite 7.3.1 funcionando
|
||
- ✅ Build funciona correctamente
|
||
- ✅ Plugins actualizados y compatibles
|
||
- ✅ Tests pasando (35 tests)
|
||
- ✅ Sin errores de lint
|
||
|
||
---
|
||
|
||
### ✅ Semana 11-12: Optimización de UX/UI y Dependencias - **COMPLETADA** (2026-01-11)
|
||
|
||
#### Mejoras de UX/UI
|
||
|
||
**Tareas:**
|
||
- ✅ Crear componente `BaseCard` unificado
|
||
- ✅ Implementar debounce en búsqueda (hook `useDebounce`)
|
||
- ✅ Añadir aria-labels a botones (Index, DecisionTreeViewer, Ictus)
|
||
- ✅ Optimizar re-renders con `React.memo` (DrugCard, ProcedureCard, TESMedicationCard, GuideCard)
|
||
- ✅ Implementar lazy loading de imágenes (ya implementado con `loading="lazy"`)
|
||
- ⏸️ Mejorar estados de carga/error consistentes (pendiente para futura iteración)
|
||
|
||
#### Actualización de Dependencias
|
||
|
||
**Tareas:**
|
||
- ⏸️ Actualizar Zod 3 → 4 (requiere análisis de breaking changes, pendiente)
|
||
- ✅ Actualizar dependencias menores (patches): @tanstack/react-query, react-hook-form, typescript-eslint
|
||
- ✅ Verificar compatibilidad (tests pasando: 35 tests)
|
||
- ✅ Testing de compatibilidad
|
||
|
||
**Deliverables:**
|
||
- ✅ Componente BaseCard unificado creado
|
||
- ✅ UX mejorada (debounce, aria-labels, optimizaciones)
|
||
- ✅ Dependencias menores actualizadas
|
||
- ⏸️ Zod 3 → 4 pendiente (requiere migración cuidadosa)
|
||
|
||
---
|
||
|
||
**🎯 MILESTONE SEMANA 12:** Stack actualizado, performance optimizado
|
||
|
||
---
|
||
|
||
## 📋 FASE 3: ESCALABILIDAD (Semanas 13-20)
|
||
|
||
### Objetivo de la Fase
|
||
**Preparar para escalabilidad y monitoreo**
|
||
|
||
**Duración:** 8 semanas
|
||
**Esfuerzo:** 160-240 horas
|
||
**Prioridad:** 🟢 MEDIA
|
||
**ROI:** ⭐⭐⭐ (Moderado)
|
||
|
||
---
|
||
|
||
### ✅ Semana 13-14: Caché y Optimización de BD - **COMPLETADA** (2026-01-11)
|
||
|
||
#### Implementar Redis Cache
|
||
|
||
**Tareas:**
|
||
- ✅ Instalar cliente: `npm install ioredis @types/ioredis`
|
||
- ✅ Crear servicio de caché (`backend/src/services/cache.ts`)
|
||
- ✅ Implementar caché para Content Pack (TTL: 1 hora)
|
||
- ✅ Implementar caché para stats (TTL: 5 minutos) - todos los endpoints
|
||
- ✅ Añadir invalidación de caché al crear/actualizar contenido
|
||
|
||
```javascript
|
||
// backend/src/services/cache.js (NUEVO)
|
||
import Redis from 'ioredis';
|
||
|
||
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
|
||
|
||
export async function get(key: string): Promise<any | null> {
|
||
const value = await redis.get(key);
|
||
return value ? JSON.parse(value) : null;
|
||
}
|
||
|
||
export async function set(key: string, value: any, ttlSeconds: number = 3600): Promise<void> {
|
||
await redis.setex(key, ttlSeconds, JSON.stringify(value));
|
||
}
|
||
|
||
export async function invalidate(pattern: string): Promise<void> {
|
||
const keys = await redis.keys(pattern);
|
||
if (keys.length > 0) {
|
||
await redis.del(...keys);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Optimización de Queries
|
||
|
||
**Tareas:**
|
||
- [ ] Analizar queries lentas con `EXPLAIN ANALYZE`
|
||
- [ ] Añadir índices faltantes si necesario
|
||
- [ ] Optimizar queries N+1 en stats
|
||
- [ ] Implementar paginación eficiente
|
||
|
||
**Deliverables:**
|
||
- ✅ Redis cache implementado
|
||
- ✅ Queries optimizadas
|
||
- ✅ Response times mejorados (~50% más rápido)
|
||
|
||
---
|
||
|
||
### ✅ Semana 15-16: Monitoring y Logging - **COMPLETADA** (2026-01-11)
|
||
|
||
#### Implementar Logging Estructurado
|
||
|
||
**Tareas:**
|
||
- ✅ Instalar Winston: `npm install winston winston-daily-rotate-file`
|
||
- ✅ Configurar logging por niveles (debug, info, warn, error)
|
||
- ✅ Añadir logging a endpoints críticos (content, auth, stats)
|
||
- ✅ Configurar rotación de logs (diaria, con compresión, retención 7-14 días)
|
||
- ✅ Middleware de request logging implementado
|
||
|
||
```javascript
|
||
// backend/src/utils/logger.js (NUEVO)
|
||
import winston from 'winston';
|
||
|
||
export const logger = winston.createLogger({
|
||
level: process.env.LOG_LEVEL || 'info',
|
||
format: winston.format.combine(
|
||
winston.format.timestamp(),
|
||
winston.format.errors({ stack: true }),
|
||
winston.format.json()
|
||
),
|
||
transports: [
|
||
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
|
||
new winston.transports.File({ filename: 'logs/combined.log' }),
|
||
new winston.transports.Console({
|
||
format: winston.format.simple()
|
||
})
|
||
],
|
||
});
|
||
```
|
||
|
||
#### Health Checks Avanzados
|
||
|
||
**Tareas:**
|
||
- ✅ Implementar health check endpoint detallado (`/api/health/detailed`)
|
||
- ✅ Verificar conexión a BD (con tiempo de respuesta)
|
||
- ✅ Verificar conexión a Redis (con tiempo de respuesta)
|
||
- ✅ Verificar espacio en disco (con alertas si >90%)
|
||
- ✅ Añadir métricas básicas (memoria, uptime, timestamp)
|
||
|
||
**Deliverables:**
|
||
- ✅ Logging estructurado implementado
|
||
- ✅ Health checks avanzados implementados
|
||
- ✅ Rotación automática de logs configurada
|
||
- ✅ Logs estructurados en formato JSON
|
||
- ✅ Métricas básicas disponibles
|
||
|
||
---
|
||
|
||
### ✅ Semana 17-18: CDN y Optimización de Assets - **COMPLETADA** (2026-01-11)
|
||
|
||
#### Configurar CDN
|
||
|
||
**Tareas:**
|
||
- ⏸️ Configurar Cloudflare o similar (pendiente - requiere configuración externa)
|
||
- ✅ Configurar cache headers apropiados (en service worker)
|
||
- ✅ Implementar service worker para offline (ya implementado)
|
||
- ⏸️ Optimizar imágenes restantes (pendiente - requiere herramientas externas)
|
||
|
||
#### Performance Frontend
|
||
|
||
**Tareas:**
|
||
- ✅ Implementar code splitting más granular (ya implementado con lazy loading)
|
||
- ✅ Añadir preloading de recursos críticos (`src/utils/preload.ts`)
|
||
- ✅ Optimizar bundle size (minificación, assets inline < 4KB)
|
||
- ✅ Implementar lazy loading de rutas (ya implementado)
|
||
- ✅ Prefetch de rutas en hover (`useRoutePrefetch` hook)
|
||
- ✅ Optimizar configuración de React Query (staleTime, gcTime, retry)
|
||
|
||
**Deliverables:**
|
||
- ✅ Preloading de recursos críticos implementado
|
||
- ✅ Prefetch de rutas implementado
|
||
- ✅ Bundle size optimizado
|
||
- ✅ React Query optimizado
|
||
- ⏸️ CDN pendiente (requiere servicio externo)
|
||
|
||
---
|
||
|
||
### Semana 19-20: Documentación y Cierre (40-60 horas)
|
||
|
||
#### Documentación Técnica
|
||
|
||
**Tareas:**
|
||
- [ ] Documentar arquitectura actualizada
|
||
- [ ] Crear guías de deployment
|
||
- [ ] Documentar APIs
|
||
- [ ] Crear guías de contribución
|
||
|
||
#### Cierre de Fase
|
||
|
||
**Tareas:**
|
||
- [ ] Revisión completa de todas las mejoras
|
||
- [ ] Testing end-to-end
|
||
- [ ] Documentar lecciones aprendidas
|
||
- [ ] Planificar siguientes pasos
|
||
|
||
**Deliverables:**
|
||
- ✅ Documentación completa
|
||
- ✅ Proyecto estable y escalable
|
||
- ✅ Plan de mantenimiento
|
||
|
||
---
|
||
|
||
**🎯 MILESTONE SEMANA 20:** Proyecto escalable y monitoreado
|
||
|
||
---
|
||
|
||
## ✅ CHECKLISTS DIARIOS/SEMANALES
|
||
|
||
### Checklist Diario (5-10 min)
|
||
|
||
```
|
||
[ ] ✅ Ejecutar tests: npm test
|
||
[ ] ✅ Verificar que build funciona: npm run build
|
||
[ ] ✅ Revisar logs de errores: tail -f logs/error.log
|
||
[ ] ✅ Verificar que app arranca: npm run dev
|
||
[ ] ✅ Commits pequeños y descriptivos
|
||
```
|
||
|
||
### Checklist Semanal (30-60 min)
|
||
|
||
```
|
||
[ ] ✅ Revisar dependencias vulnerables: npm audit
|
||
[ ] ✅ Verificar dependencias no usadas: npx depcheck
|
||
[ ] ✅ Revisar código muerto: npx ts-prune | head -20
|
||
[ ] ✅ Ejecutar lint: npm run lint
|
||
[ ] ✅ Actualizar documentación de cambios
|
||
[ ] ✅ Revisar métricas de performance
|
||
[ ] ✅ Backup de base de datos (si aplica)
|
||
```
|
||
|
||
### Checklist por Milestone
|
||
|
||
**Milestone 1 (Semana 4):**
|
||
- [ ] ✅ Todas las vulnerabilidades críticas resueltas
|
||
- [ ] ✅ Rate limiting activo
|
||
- [ ] ✅ Security headers configurados
|
||
- [ ] ✅ Test suite básico funcionando (20% cobertura)
|
||
- [ ] ✅ Backend parcialmente migrado a TypeScript
|
||
|
||
**Milestone 2 (Semana 12):**
|
||
- [ ] ✅ Backend 100% TypeScript
|
||
- [ ] ✅ React 19 funcionando
|
||
- [ ] ✅ Vite 7 funcionando
|
||
- [ ] ✅ Assets optimizados (30MB → 4MB)
|
||
- [ ] ✅ UX mejorada (componentes unificados)
|
||
|
||
**Milestone 3 (Semana 20):**
|
||
- [ ] ✅ Redis cache implementado
|
||
- [ ] ✅ Logging estructurado activo
|
||
- [ ] ✅ Monitoring configurado
|
||
- [ ] ✅ CDN configurado
|
||
- [ ] ✅ Documentación completa
|
||
|
||
---
|
||
|
||
## 📊 SISTEMA DE SEGUIMIENTO
|
||
|
||
### Métricas de Progreso
|
||
|
||
**Métricas Técnicas:**
|
||
- Cobertura de tests: 0% → 60% objetivo
|
||
- Vulnerabilidades críticas: 6 → 0
|
||
- Bundle size: Actual → -30% objetivo
|
||
- Response time API: Actual → -50% objetivo
|
||
- Código TypeScript: 50% → 100%
|
||
|
||
**Métricas de Calidad:**
|
||
- Code quality score: 6.2/10 → 8.5/10 objetivo
|
||
- Deuda técnica: Alta → Media
|
||
- Documentación: Básica → Completa
|
||
|
||
### Dashboard de Progreso
|
||
|
||
```typescript
|
||
// Crear: scripts/progress-dashboard.ts (OPCIONAL)
|
||
// Dashboard simple para tracking de progreso
|
||
|
||
interface ProgressMetric {
|
||
name: string;
|
||
current: number;
|
||
target: number;
|
||
unit: string;
|
||
}
|
||
|
||
const metrics: ProgressMetric[] = [
|
||
{ name: 'Test Coverage', current: 0, target: 60, unit: '%' },
|
||
{ name: 'Critical Vulnerabilities', current: 6, target: 0, unit: '' },
|
||
{ name: 'TypeScript Coverage (Backend)', current: 50, target: 100, unit: '%' },
|
||
{ name: 'Assets Size', current: 36, target: 4, unit: 'MB' },
|
||
];
|
||
|
||
// Generar reporte semanal
|
||
```
|
||
|
||
### Reportes Semanales
|
||
|
||
**Formato de Reporte Semanal:**
|
||
|
||
```markdown
|
||
# Reporte Semanal - Semana X
|
||
|
||
## ✅ Completado
|
||
- [Lista de tareas completadas]
|
||
|
||
## 🚧 En Progreso
|
||
- [Lista de tareas en progreso]
|
||
|
||
## ⚠️ Bloqueos
|
||
- [Lista de bloqueos y cómo resolverlos]
|
||
|
||
## 📊 Métricas
|
||
- Test Coverage: X% (↑ Y% desde última semana)
|
||
- Vulnerabilidades: X (↓ Y desde última semana)
|
||
- Assets Size: X MB (↓ Y MB desde última semana)
|
||
|
||
## 🎯 Próxima Semana
|
||
- [Objetivos para próxima semana]
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 PLANTILLAS REUTILIZABLES
|
||
|
||
### Plantilla de Pull Request
|
||
|
||
```markdown
|
||
## Descripción
|
||
[Descripción breve de los cambios]
|
||
|
||
## Tipo de Cambio
|
||
- [ ] 🐛 Bug fix
|
||
- [ ] ✨ Nueva feature
|
||
- [ ] 🔧 Refactor
|
||
- [ ] 📝 Documentación
|
||
- [ ] ⚡ Performance
|
||
- [ ] 🔒 Seguridad
|
||
|
||
## Checklist
|
||
- [ ] Tests añadidos/actualizados
|
||
- [ ] Documentación actualizada
|
||
- [ ] Build pasa correctamente
|
||
- [ ] Lint pasa correctamente
|
||
- [ ] No hay vulnerabilidades nuevas (npm audit)
|
||
- [ ] Cambios probados localmente
|
||
|
||
## Screenshots (si aplica)
|
||
[Capturas de pantalla]
|
||
|
||
## Testing
|
||
[Descripción de cómo probar los cambios]
|
||
```
|
||
|
||
### Plantilla de Issue
|
||
|
||
```markdown
|
||
## Descripción
|
||
[Descripción del problema o feature]
|
||
|
||
## Prioridad
|
||
- [ ] 🔴 Crítica
|
||
- [ ] 🟡 Alta
|
||
- [ ] 🟢 Media
|
||
- [ ] ⚪ Baja
|
||
|
||
## Criterios de Aceptación
|
||
- [ ] [Criterio 1]
|
||
- [ ] [Criterio 2]
|
||
- [ ] [Criterio 3]
|
||
|
||
## Archivos Afectados
|
||
- `ruta/archivo.ts`
|
||
|
||
## Esfuerzo Estimado
|
||
[X horas]
|
||
```
|
||
|
||
### Plantilla de Commit
|
||
|
||
```
|
||
<type>(<scope>): <subject>
|
||
|
||
<body>
|
||
|
||
<footer>
|
||
|
||
Tipos:
|
||
- feat: Nueva feature
|
||
- fix: Bug fix
|
||
- refactor: Refactorización
|
||
- perf: Mejora de performance
|
||
- test: Tests
|
||
- docs: Documentación
|
||
- chore: Mantenimiento
|
||
- security: Fix de seguridad
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 RESUMEN FINAL
|
||
|
||
### Objetivos Alcanzados (Al Final del Plan)
|
||
|
||
✅ **Seguridad:** 5.1/10 → 9.0/10
|
||
✅ **Performance:** Assets optimizados (-83%)
|
||
✅ **Calidad:** Backend TypeScript (100%)
|
||
✅ **Modernización:** React 19, Vite 7
|
||
✅ **Testing:** 0% → 60% cobertura
|
||
✅ **Escalabilidad:** Cache + Monitoring
|
||
|
||
### Estado Final Esperado
|
||
|
||
**Calificación Final: 8.5/10** ✅ **EXCELENTE Y ESCALABLE**
|
||
|
||
**Total de Mejoras Implementadas:**
|
||
- 🔒 6 vulnerabilidades críticas eliminadas
|
||
- ⚡ 30 MB de assets optimizados
|
||
- 📝 100% backend TypeScript
|
||
- 🧪 Suite de tests completa
|
||
- 📊 Monitoring y logging implementados
|
||
- 🚀 Stack actualizado (React 19, Vite 7)
|
||
|
||
---
|
||
|
||
---
|
||
|
||
## 📋 CHECKLIST DE INICIO RÁPIDO
|
||
|
||
### Pre-requisitos
|
||
|
||
```bash
|
||
# 1. Verificar herramientas instaladas
|
||
node --version # >= 18.0.0
|
||
npm --version # >= 9.0.0
|
||
git --version # >= 2.30.0
|
||
|
||
# 2. Instalar herramientas opcionales
|
||
sudo apt-get install imagemagick webp pngquant # Para optimización de imágenes
|
||
docker --version # Para Redis (opcional)
|
||
|
||
# 3. Verificar variables de entorno
|
||
cat .env | grep -E "JWT_SECRET|DB_|CORS"
|
||
```
|
||
|
||
### Setup Inicial (Día 1)
|
||
|
||
```bash
|
||
# 1. Clonar o actualizar repositorio
|
||
git pull origin main
|
||
|
||
# 2. Instalar dependencias
|
||
npm install
|
||
cd backend && npm install
|
||
cd ../admin-panel && npm install
|
||
|
||
# 3. Verificar que app arranca
|
||
npm run dev # Frontend
|
||
cd backend && npm run dev # Backend
|
||
|
||
# 4. Ejecutar tests existentes (si hay)
|
||
npm test
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ SCRIPTS DE AUTOMATIZACIÓN
|
||
|
||
### Script de Verificación Pre-Deploy
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/verify-pre-deploy.sh
|
||
|
||
echo "🔍 Verificando estado del proyecto antes de deploy..."
|
||
|
||
# 1. Verificar que tests pasan
|
||
echo "📋 Ejecutando tests..."
|
||
npm test || { echo "❌ Tests fallan"; exit 1; }
|
||
|
||
# 2. Verificar que build funciona
|
||
echo "📦 Verificando build..."
|
||
npm run build || { echo "❌ Build falla"; exit 1; }
|
||
|
||
# 3. Verificar vulnerabilidades
|
||
echo "🔒 Verificando vulnerabilidades..."
|
||
npm audit --audit-level=moderate || { echo "⚠️ Vulnerabilidades encontradas"; exit 1; }
|
||
|
||
# 4. Verificar lint
|
||
echo "🧹 Verificando lint..."
|
||
npm run lint || { echo "⚠️ Errores de lint encontrados"; exit 1; }
|
||
|
||
# 5. Verificar variables de entorno críticas
|
||
echo "🔑 Verificando variables de entorno..."
|
||
if [ -z "$JWT_SECRET" ]; then
|
||
echo "❌ JWT_SECRET no configurado"
|
||
exit 1
|
||
fi
|
||
|
||
if [ -z "$DB_HOST" ]; then
|
||
echo "❌ DB_HOST no configurado"
|
||
exit 1
|
||
fi
|
||
|
||
echo "✅ Todas las verificaciones pasaron"
|
||
```
|
||
|
||
### Script de Actualización de Dependencias
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/update-dependencies.sh
|
||
|
||
echo "📦 Actualizando dependencias..."
|
||
|
||
# Frontend
|
||
echo "🖥️ Actualizando frontend..."
|
||
cd /home/planetazuzu/guia-tes
|
||
npm update
|
||
npm audit fix
|
||
|
||
# Backend
|
||
echo "⚙️ Actualizando backend..."
|
||
cd backend
|
||
npm update
|
||
npm audit fix
|
||
|
||
# Admin Panel
|
||
echo "👨💼 Actualizando admin panel..."
|
||
cd ../admin-panel
|
||
npm update
|
||
npm audit fix
|
||
|
||
echo "✅ Dependencias actualizadas"
|
||
echo "⚠️ Recuerda ejecutar tests después de actualizar"
|
||
```
|
||
|
||
### Script de Limpieza Automática
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/auto-cleanup.sh
|
||
|
||
echo "🧹 Limpieza automática del proyecto..."
|
||
|
||
# 1. Eliminar node_modules y reinstalar
|
||
echo "🗑️ Limpiando node_modules..."
|
||
rm -rf node_modules package-lock.json
|
||
npm install
|
||
|
||
# 2. Eliminar dist y rebuild
|
||
echo "🗑️ Limpiando dist..."
|
||
rm -rf dist
|
||
npm run build
|
||
|
||
# 3. Eliminar logs antiguos (>7 días)
|
||
echo "🗑️ Limpiando logs antiguos..."
|
||
find logs -type f -name "*.log" -mtime +7 -delete
|
||
|
||
# 4. Eliminar backups antiguos
|
||
echo "🗑️ Limpiando backups antiguos..."
|
||
find . -name "*.backup" -mtime +30 -delete
|
||
|
||
echo "✅ Limpieza completada"
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 MÉTRICAS DE ÉXITO
|
||
|
||
### KPIs por Fase
|
||
|
||
**Fase 1: Estabilización (Semanas 1-4)**
|
||
- ✅ Vulnerabilidades críticas: 6 → 0
|
||
- ✅ Test coverage: 0% → 20%
|
||
- ✅ TypeScript backend: 0% → 50%
|
||
- ✅ Assets optimizados: 30 MB → 15 MB
|
||
|
||
**Fase 2: Optimización (Semanas 5-12)**
|
||
- ✅ TypeScript backend: 50% → 100%
|
||
- ✅ React actualizado: 18.3 → 19.2
|
||
- ✅ Vite actualizado: 5.4 → 7.3
|
||
- ✅ Assets optimizados: 15 MB → 4 MB
|
||
- ✅ Test coverage: 20% → 50%
|
||
|
||
**Fase 3: Escalabilidad (Semanas 13-20)**
|
||
- ✅ Redis cache: 0% → 100% (endpoints críticos)
|
||
- ✅ Logging estructurado: 0% → 100%
|
||
- ✅ Health checks: Básico → Avanzado
|
||
- ✅ CDN configurado: No → Sí
|
||
- ✅ Test coverage: 50% → 60%
|
||
|
||
### Métricas Técnicas Objetivo
|
||
|
||
| Métrica | Inicial | Objetivo | Estado Actual |
|
||
|---------|---------|----------|---------------|
|
||
| **Test Coverage** | 0% | 60% | 0% |
|
||
| **TypeScript Backend** | 0% | 100% | 0% |
|
||
| **Assets Size** | 36 MB | 4 MB | 36 MB |
|
||
| **Bundle Size (Frontend)** | ? KB | -30% | ? KB |
|
||
| **API Response Time** | ? ms | -50% | ? ms |
|
||
| **Vulnerabilidades Críticas** | 6 | 0 | 6 |
|
||
| **Security Score** | 5.1/10 | 9.0/10 | 5.1/10 |
|
||
| **Code Quality Score** | 6.2/10 | 8.5/10 | 6.2/10 |
|
||
|
||
---
|
||
|
||
## 🔄 PROCESO DE REVISIÓN
|
||
|
||
### Revisión Semanal
|
||
|
||
**Cuándo:** Cada viernes
|
||
**Duración:** 30-60 minutos
|
||
**Participantes:** Equipo completo
|
||
|
||
**Agenda:**
|
||
1. ✅ Revisar checklist semanal (5 min)
|
||
2. 📊 Revisar métricas de progreso (10 min)
|
||
3. 🚧 Discutir bloqueos y soluciones (15 min)
|
||
4. 🎯 Planificar próxima semana (15 min)
|
||
5. 📝 Actualizar documentación (15 min)
|
||
|
||
### Revisión de Milestone
|
||
|
||
**Cuándo:** Al final de cada fase (Semanas 4, 12, 20)
|
||
**Duración:** 2-3 horas
|
||
**Participantes:** Equipo completo + Stakeholders
|
||
|
||
**Agenda:**
|
||
1. ✅ Revisar checklist de milestone (15 min)
|
||
2. 📊 Presentar métricas alcanzadas (30 min)
|
||
3. 🎯 Demostrar mejoras implementadas (60 min)
|
||
4. 🚧 Discutir bloqueos y ajustes (30 min)
|
||
5. 📝 Planificar siguiente fase (30 min)
|
||
6. 📋 Retrospectiva y lecciones aprendidas (15 min)
|
||
|
||
---
|
||
|
||
## 🚨 GESTIÓN DE RIESGOS
|
||
|
||
### Riesgos Identificados
|
||
|
||
| Riesgo | Probabilidad | Impacto | Mitigación | Contingencia |
|
||
|--------|--------------|---------|------------|--------------|
|
||
| **Breaking changes en migraciones** | Media | Alto | Feature flags, tests incrementales | Rollback plan preparado |
|
||
| **Tiempo subestimado** | Alta | Medio | Buffer 20% en cada fase | Priorizar tareas críticas |
|
||
| **Regresiones** | Media | Alto | Tests automatizados antes de cada release | Hotfix plan preparado |
|
||
| **Conflicto con features nuevas** | Baja | Medio | Priorizar estabilidad sobre features | Pausar features si necesario |
|
||
| **Vulnerabilidades durante migración** | Baja | Alto | Security reviews antes de merge | Security hotfix protocol |
|
||
| **Dependencias incompatibles** | Media | Medio | Testear en branch separado primero | Mantener versión anterior si necesario |
|
||
|
||
### Plan de Contingencia
|
||
|
||
**Si hay breaking changes:**
|
||
1. Crear branch `hotfix/[issue]`
|
||
2. Implementar fix
|
||
3. Ejecutar tests completos
|
||
4. Merge a `main` si todos los tests pasan
|
||
5. Deploy inmediato
|
||
|
||
**Si hay regresiones:**
|
||
1. Identificar commit que causó regresión
|
||
2. Crear revert PR
|
||
3. Ejecutar tests
|
||
4. Deploy revert
|
||
|
||
**Si hay vulnerabilidades:**
|
||
1. Evaluar severidad
|
||
2. Si crítica: Fix inmediato (<24 horas)
|
||
3. Si alta: Fix en 1 semana
|
||
4. Si media: Fix en siguiente milestone
|
||
|
||
---
|
||
|
||
## 📚 RECURSOS ADICIONALES
|
||
|
||
### Documentación Técnica de Referencia
|
||
|
||
- **React 19 Migration Guide:** https://react.dev/blog/2024/04/25/react-19
|
||
- **Vite 7 Migration Guide:** https://vitejs.dev/guide/migration
|
||
- **TypeScript Migration Guide:** https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html
|
||
- **Security Best Practices:** https://owasp.org/www-project-top-ten/
|
||
- **Performance Best Practices:** https://web.dev/performance/
|
||
|
||
### Herramientas Recomendadas
|
||
|
||
**Análisis de Código:**
|
||
- `ts-prune` - Detectar código muerto
|
||
- `depcheck` - Detectar dependencias no usadas
|
||
- `npm audit` - Verificar vulnerabilidades
|
||
- `lighthouse` - Análisis de performance
|
||
|
||
**Testing:**
|
||
- `Jest` - Framework de testing
|
||
- `React Testing Library` - Testing de componentes
|
||
- `Vitest` - Testing rápido (alternativa a Jest)
|
||
- `Playwright` - Testing E2E
|
||
|
||
**Monitoreo:**
|
||
- `Winston` - Logging estructurado
|
||
- `PM2` - Process manager
|
||
- `Prometheus` - Métricas (opcional)
|
||
- `Grafana` - Dashboards (opcional)
|
||
|
||
---
|
||
|
||
## 🎓 CAPACITACIÓN Y APRENDIZAJE
|
||
|
||
### Recursos de Aprendizaje
|
||
|
||
**TypeScript:**
|
||
- TypeScript Handbook: https://www.typescriptlang.org/docs/handbook/intro.html
|
||
- TypeScript Deep Dive: https://basarat.gitbook.io/typescript/
|
||
|
||
**React 19:**
|
||
- React Documentation: https://react.dev
|
||
- React Beta Docs: https://react.dev/blog/2024/04/25/react-19
|
||
|
||
**Seguridad:**
|
||
- OWASP Top 10: https://owasp.org/www-project-top-ten/
|
||
- Node.js Security Best Practices: https://nodejs.org/en/docs/guides/security/
|
||
|
||
**Performance:**
|
||
- Web.dev Performance: https://web.dev/performance/
|
||
- Vite Performance Guide: https://vitejs.dev/guide/performance.html
|
||
|
||
### Prácticas Recomendadas
|
||
|
||
**Commits:**
|
||
- Commits pequeños y frecuentes
|
||
- Mensajes descriptivos siguiendo Conventional Commits
|
||
- Revisar código antes de commit (git diff)
|
||
|
||
**Pull Requests:**
|
||
- PRs pequeños (< 500 líneas cuando sea posible)
|
||
- Descripción clara de cambios
|
||
- Checklist completado
|
||
- Tests pasando
|
||
- Lint pasando
|
||
|
||
**Testing:**
|
||
- Test-driven development (TDD) cuando sea posible
|
||
- Tests antes de refactoring
|
||
- Cobertura mínima: 60% para código crítico
|
||
|
||
---
|
||
|
||
## 📞 SOPORTE Y CONTACTO
|
||
|
||
### En caso de bloqueos
|
||
|
||
1. **Revisar documentación:** Buscar en `docs/`
|
||
2. **Buscar en issues:** GitHub issues existentes
|
||
3. **Crear issue:** Si no existe, crear uno nuevo con label `blocked`
|
||
4. **Contactar equipo:** Slack/email para discusión rápida
|
||
|
||
### Canales de Comunicación
|
||
|
||
- **Issues de GitHub:** Para bugs y features
|
||
- **Discusiones de GitHub:** Para preguntas técnicas
|
||
- **Slack/Email:** Para comunicación rápida (si aplica)
|
||
|
||
---
|
||
|
||
## ✅ RESUMEN FINAL
|
||
|
||
### Objetivos Alcanzados (Al Final del Plan)
|
||
|
||
✅ **Seguridad:** 5.1/10 → 9.0/10 (eliminar vulnerabilidades críticas)
|
||
✅ **Performance:** Assets optimizados de 36 MB → 4 MB (-89%)
|
||
✅ **Calidad:** Backend migrado a TypeScript (100%)
|
||
✅ **Modernización:** React 19, Vite 7 (stack actualizado)
|
||
✅ **Testing:** 0% → 60% cobertura (suite de tests completa)
|
||
✅ **Escalabilidad:** Redis cache + Monitoring + CDN configurado
|
||
✅ **Limpieza:** Código muerto eliminado, dependencias actualizadas
|
||
✅ **Documentación:** Completa y actualizada
|
||
|
||
### Estado Final Esperado
|
||
|
||
**Calificación Final: 8.5/10** ✅ **EXCELENTE Y ESCALABLE**
|
||
|
||
**Total de Mejoras Implementadas:**
|
||
- 🔒 6 vulnerabilidades críticas eliminadas
|
||
- ⚡ 32 MB de assets optimizados (89% reducción)
|
||
- 📝 100% backend TypeScript (mejor mantenibilidad)
|
||
- 🧪 Suite de tests completa (60% cobertura objetivo)
|
||
- 📊 Monitoring y logging estructurado implementado
|
||
- 🚀 Stack actualizado (React 19, Vite 7)
|
||
- 🧹 Código limpio (dead code eliminado, dependencias actualizadas)
|
||
- 📚 Documentación completa
|
||
|
||
### Próximos Pasos Post-Plan
|
||
|
||
**Después de completar este plan (Semanas 21-24):**
|
||
1. Monitorear métricas de producción
|
||
2. Recopilar feedback de usuarios
|
||
3. Planificar features nuevas basadas en feedback
|
||
4. Mantener actualizaciones incrementales
|
||
5. Continuar mejorando cobertura de tests (objetivo: 80%)
|
||
6. Evaluar nuevas tecnologías relevantes
|
||
|
||
---
|
||
|
||
**Última actualización:** 2026-01-19
|
||
**Versión del Plan:** 1.0.0
|
||
**Próxima revisión:** Semanal durante implementación (Viernes de cada semana)
|
||
**Responsable:** Equipo de Desarrollo
|
||
**Aprobado por:** [Nombre del responsable]
|