Files
math2-platform/docs/ARCHITECTURE.md
Renato bc43c9e772
Some checks failed
Test Suite / test-backend (push) Has been cancelled
Test Suite / test-frontend (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / coverage-check (push) Has been cancelled
🎓 Initial commit: Math2 Platform - Plataforma de Álgebra Lineal PRO
 Características:
- 45 ejercicios universitarios (Basic → Advanced)
- Renderizado LaTeX profesional
- IA generativa (Z.ai/DashScope)
- Docker 9 servicios
- Tests 123/123 pasando
- Seguridad enterprise (JWT, XSS, Rate limiting)

🐳 Infraestructura:
- Next.js 14 + Node.js 20
- PostgreSQL 15 + Redis 7
- Docker Compose completo
- Nginx + SSL ready

📚 Documentación:
- 5 informes técnicos completos
- README profesional
- Scripts de deployment automatizados

Estado: Producción lista 
2026-03-31 11:27:11 -03:00

14 KiB

Arquitectura del Sistema

Stack Tecnológico

Frontend

  • Framework: Next.js 14 (App Router)
  • Lenguaje: TypeScript 5.4 (strict mode)
  • Estilos: Tailwind CSS 3.4 + shadcn/ui
  • State Management: Zustand 4.5
  • HTTP Client: Axios 1.6
  • Validación: Zod 3.22 + react-hook-form
  • Testing: Vitest 1.3 + React Testing Library 14
  • Math Rendering: KaTeX 0.16 + react-katex

Backend

  • Runtime: Node.js 20 LTS
  • Framework: Express.js 4.18
  • Lenguaje: TypeScript 5.4
  • ORM: Prisma 5.11
  • Database: PostgreSQL 15
  • Cache/Queue: Redis 7
  • Auth: JWT (jsonwebtoken) + bcrypt
  • Validation: Zod 3.22
  • Logging: Winston 3.12 (JSON structured)
  • Rate Limiting: express-rate-limit + rate-limit-redis
  • Security: Helmet.js, CORS, DOMPurify
  • Testing: Vitest 1.3 + Supertest 6.3

Infrastructure

  • Container: Docker 24 + Docker Compose
  • Reverse Proxy: Nginx 1.24
  • Queue System: Bull 4.12 + Redis
  • AI Service: MiniMax-M2.5 (Aliyun DashScope)
  • Notifications: Telegram Bot API
  • PDF Processing: pdf-parse + pdf2pic

Patrones de Diseño

1. Repository Pattern

Controller → Service → Repository → Database

Flujo de datos:

  1. Controller: Maneja HTTP requests/responses, validación de entrada
  2. Service: Lógica de negocio, coordinación entre repositorios
  3. Repository: Acceso a datos, queries Prisma
  4. Database: PostgreSQL con Prisma ORM

Ejemplo:

// ExerciseController.ts
async getExercise(req: Request, res: Response) {
  const { id } = req.params;
  const exercise = await this.exerciseService.getById(id);
  res.json({ success: true, data: exercise });
}

// ExerciseService.ts
async getById(id: string) {
  const exercise = await this.exerciseRepository.findById(id);
  if (!exercise) throw new NotFoundError('Exercise not found');
  return exercise;
}

// ExerciseRepository.ts
async findById(id: string) {
  return prisma.exercise.findUnique({
    where: { id },
    include: { topic: true, module: true }
  });
}

2. Dependency Injection

Usando TSyringe para inversión de control:

// Container setup
container.register<IExerciseRepository>('ExerciseRepository', {
  useClass: ExerciseRepository
});

container.register<ExerciseService>('ExerciseService', {
  useClass: ExerciseService
});

// Controller injection
@injectable()
class ExerciseController {
  constructor(
    @inject('ExerciseService') private service: ExerciseService
  ) {}
}

3. Middleware Pipeline

Request → Security → Auth → Validation → Rate Limit → Handler → Response

Orden de middlewares:

  1. Helmet - Security headers
  2. CORS - Cross-origin handling
  3. Compression - gzip/deflate
  4. Request ID - Correlation ID injection
  5. Logging - Request/response logging
  6. Auth - JWT verification
  7. Rate Limit - Throttling
  8. Validation - Zod schema validation
  9. Handler - Route controller
  10. Error Handler - Centralized error handling

Estructura de Módulos

Backend Modules

src/modules/
├── auth/                    # Autenticación y autorización
│   ├── controllers/
│   ├── services/
│   ├── repositories/
│   ├── middleware/
│   └── types/
├── exercise/                # Gestión de ejercicios
│   ├── controllers/
│   ├── services/
│   ├── repositories/
│   └── types/
├── module/                  # Módulos pedagógicos
├── topic/                   # Temas de estudio
├── progress/                # Progreso del usuario
├── ranking/                 # Sistema de rankings
├── achievement/             # Logros y gamificación
├── pdf/                     # Procesamiento de PDFs
├── notification/            # Notificaciones (Telegram)
└── ai/                      # Integración con AI

Frontend Structure

src/
├── app/                     # Next.js App Router
│   ├── layout.tsx          # Root layout
│   ├── page.tsx            # Home page
│   ├── auth/               # Auth routes
│   ├── dashboard/          # Dashboard routes
│   ├── modules/            # Module routes
│   ├── exercises/          # Exercise routes
│   └── api/                # API routes
├── components/
│   ├── ui/                 # shadcn/ui components
│   ├── math/               # Math components (KaTeX)
│   ├── auth/               # Auth components
│   ├── exercises/          # Exercise components
│   └── layout/             # Layout components
├── lib/
│   ├── api.ts             # API client
│   ├── utils.ts           # Utilities
│   ├── validators.ts      # Zod schemas
│   └── constants.ts       # App constants
├── store/
│   ├── useAuthStore.ts    # Auth state
│   ├── useModuleStore.ts  # Module state
│   └── useExerciseStore.ts # Exercise state
├── hooks/
│   ├── useAuth.ts         # Auth hook
│   └── useProgress.ts     # Progress hook
└── types/
    └── index.ts           # TypeScript definitions

Seguridad

Autenticación

  1. Login Flow:

    • Client envía credentials
    • Server valida con bcrypt
    • Genera access token (15 min) + refresh token (7 días)
    • Refresh tokens almacenados en Redis blacklist
    • JWT firmado con HS256 y secret seguro
  2. Token Refresh:

    • Access token expira después de 15 minutos
    • Client usa refresh token para obtener nuevo access token
    • Refresh token rota en cada uso
    • Tokens antiguos agregados a blacklist
  3. Logout:

    • Agrega refresh token a Redis blacklist
    • Client elimina tokens del storage
    • TTL en Redis coincide con expiración del token

Autorización

  1. RBAC (Role-Based Access Control):

    • Roles: USER, TEACHER, ADMIN
    • Permisos definidos por rol
    • Middleware requireAdmin para rutas sensibles
  2. Resource Ownership:

    • Verificación de ownership en recursos
    • Usuarios solo acceden a sus propios datos
    • Teachers pueden ver datos de sus estudiantes

Protección Web

  1. XSS Protection:

    • DOMPurify para sanitización de LaTeX
    • Helmet.js headers (CSP, X-Frame-Options)
    • Escape de output en templates
  2. CSRF Protection:

    • Tokens CSRF en formularios
    • Validación de Origin header
    • SameSite cookies
  3. SQL Injection:

    • Uso exclusivo de Prisma ORM
    • No queries raw sin validación
    • Prepared statements automáticos
  4. Input Validation:

    • Zod schemas en todos los endpoints
    • Validación de tipo y formato
    • Sanitización de input

Escalabilidad

Horizontal Scaling

  • Docker Swarm / Kubernetes ready
  • Stateless backend design - No session state en servidor
  • Redis Cluster para sessions y cache
  • PostgreSQL Read Replicas para queries de lectura

Database Optimization

  1. Connection Pooling:

    • PgBouncer para pooling de conexiones
    • Prisma connection limits configurados
    • Min/Max connections según carga
  2. Query Optimization:

    • Índices en campos de búsqueda frecuente
    • Select fields específicos (no SELECT *)
    • Caching de queries frecuentes en Redis
  3. Read Replicas:

    • Replicas para queries de lectura
    • Master para writes
    • Prisma read replica strategy

Caching Strategy

  1. Redis Cache:

    • Session storage (JWT blacklist)
    • Exercise data (TTL: 1 hora)
    • Progress data (TTL: 5 minutos)
    • Rankings (TTL: 1 minuto)
  2. CDN:

    • Assets estáticos en CDN
    • KaTeX fonts y CSS
    • Imágenes y PDFs

Workers y Queue System

Bull Queue Configuration

const exerciseQueue = new Bull('exercise-generation', {
  redis: { host: REDIS_HOST, port: REDIS_PORT },
  defaultJobOptions: {
    attempts: 3,
    backoff: { type: 'exponential', delay: 2000 },
    removeOnComplete: 100,
    removeOnFail: 50
  }
});

Workers

  1. PDF Worker:

    • Procesa PDFs de /app/pdfs
    • Extrae texto con pdf-parse
    • Genera imágenes con pdf2pic
    • Almacena metadata en ProcessedPdf
  2. Exercise Worker:

    • Genera ejercicios con AI
    • Conecta a MiniMax-M2.5 API
    • Valida notación matemática
    • Guarda en database
  3. Notification Worker:

    • Envía notificaciones Telegram
    • Procesa cola de notificaciones
    • Rate limiting para bot API

Escalado de Workers

# Escalar a 3 workers
docker-compose up -d --scale exercise-worker=3

# Load balancing automático por Bull
# Cada worker procesa jobs de la cola

Observabilidad

Logging

Winston Configuration:

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  defaultMeta: {
    service: 'math-platform-api',
    version: process.env.npm_package_version
  },
  transports: [
    new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
    new winston.transports.File({ filename: 'logs/combined.log' })
  ]
});

Correlation IDs:

  • UUID generado en middleware
  • Propagado a todos los servicios
  • Incluido en logs y respuestas de error

Health Checks

// Health check endpoint
app.get('/health', async (req, res) => {
  const checks = {
    database: await checkDatabase(),
    redis: await checkRedis(),
    ai: await checkAIService()
  };
  
  const healthy = Object.values(checks).every(c => c.status === 'up');
  
  res.status(healthy ? 200 : 503).json({
    status: healthy ? 'healthy' : 'unhealthy',
    timestamp: new Date().toISOString(),
    version: process.env.npm_package_version,
    checks
  });
});

Docker Health Checks

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Flujo de Datos

Autenticación

┌─────────┐     ┌──────────┐     ┌────────────┐     ┌──────────┐
│ Client  │────▶│  Nginx   │────▶│  Backend   │────▶│ PostgreSQL│
└─────────┘     └──────────┘     └────────────┘     └──────────┘
                                      │
                                      ▼
                                ┌──────────┐
                                │  Redis   │
                                │ Blacklist│
                                └──────────┘

Ejercicio Attempt

┌─────────┐     ┌──────────┐     ┌─────────────┐
│ Client  │────▶│  Backend  │────▶│  Validation  │
└─────────┘     └──────────┘     └─────────────┘
                                      │
                    ┌─────────────────┼─────────────────┐
                    ▼                 ▼                 ▼
             ┌──────────┐      ┌──────────┐     ┌──────────┐
             │ PostgreSQL│      │  Redis   │     │  AI API  │
             │  Score   │      │ Progress │     │ Validate │
             └──────────┘      └──────────┘     └──────────┘

AI Exercise Generation

┌─────────┐     ┌──────────┐     ┌───────────────┐
│ Client  │────▶│  Backend  │────▶│  Bull Queue   │
└─────────┘     └──────────┘     └───────────────┘
                                         │
                                         ▼
                              ┌─────────────────────┐
                              │   Exercise Worker   │
                              │  (MiniMax-M2.5 API) │
                              └─────────────────────┘
                                         │
                                         ▼
                              ┌─────────────────────┐
                              │     PostgreSQL      │
                              │   (Store Exercise)  │
                              └─────────────────────┘

Configuración de Entorno

Variables de Entorno

# Database
DATABASE_URL="postgresql://user:pass@localhost:5432/mathdb"
DB_PASSWORD="secure_password"

# Redis
REDIS_HOST="redis"
REDIS_PORT=6379
REDIS_PASSWORD="redis_password"

# JWT
JWT_SECRET="your-super-secret-jwt-key-min-32-chars"
JWT_EXPIRES_IN="15m"
JWT_REFRESH_EXPIRES_IN="7d"

# AI
AI_API_BASE_URL="https://api.example.com/v1"
AI_API_KEY="your-ai-api-key"
AI_MODEL="MiniMax-M2.5"

# Telegram
TELEGRAM_BOT_TOKEN="your-bot-token"
TELEGRAM_ADMIN_CHAT_ID="admin-chat-id"

# App
NODE_ENV="production"
PORT=3001
LOG_LEVEL="info"

Perfiles de Entorno

  1. Development:

    • Hot reload habilitado
    • Logging detallado
    • Prisma Studio disponible
    • Mock services
  2. Staging:

    • Docker containers
    • SSL/TLS habilitado
    • CI/CD deployment
    • Test data
  3. Production:

    • Multi-stage Docker builds
    • SSL/TLS con Let's Encrypt
    • Read replicas
    • CDN activo
    • Monitoring completo

Convenciones de Código

TypeScript

  • Siempre tipos explícitos (no any)
  • Interfaces para objetos complejos
  • Enums para valores fijos
  • Never usar console.log (usar logger)
  • Strict mode enabled
  • Path aliases (@/components, @/lib)

Nomenclatura

  • Components: PascalCase (ExerciseSolver.tsx)
  • Hooks: camelCase con use (useAuth.ts)
  • Utils: camelCase (formatDate.ts)
  • Constants: UPPER_SNAKE_CASE
  • Types/Interfaces: PascalCase con sufijo Type (UserType)
  • Enums: PascalCase (ExerciseDifficulty)

Testing

  • Cada feature necesita tests
  • Cobertura mínima: 70%
  • E2E para flows críticos
  • Mock de servicios externos
  • Tests de integración para DB