# AN-005: Análisis de Riesgos Técnicos

**Proyecto:** Sistema de Registro de Estudiantes - Inter Rapidísimo
**Rol:** Líder Técnico
**Fecha:** 2026-01-07

---

## 1. Resumen

Identificación y evaluación de riesgos técnicos que podrían impactar el desarrollo, calidad o entrega del sistema. Cada riesgo incluye probabilidad, impacto y estrategia de mitigación.

---

## 2. Matriz de Evaluación

| Probabilidad / Impacto | Bajo (1) | Medio (2) | Alto (3) |
|------------------------|----------|-----------|----------|
| **Alta (3)** | 3 | 6 | **9** |
| **Media (2)** | 2 | 4 | 6 |
| **Baja (1)** | 1 | 2 | 3 |

**Clasificación:**
- **Crítico:** 6-9 (acción inmediata)
- **Moderado:** 3-5 (plan de mitigación)
- **Bajo:** 1-2 (monitorear)

---

## 3. Riesgos Identificados

### RT-001: Complejidad de Validaciones Cruzadas

| Atributo | Valor |
|----------|-------|
| **ID** | RT-001 |
| **Categoría** | Desarrollo |
| **Probabilidad** | Alta (3) |
| **Impacto** | Alto (3) |
| **Score** | **9 - Crítico** |

**Descripción:**
Las validaciones de negocio (máximo 3 materias + no repetir profesor) requieren consultas cruzadas entre entidades. Una implementación incorrecta puede generar condiciones de carrera o validaciones inconsistentes.

**Escenarios de Riesgo:**
1. Dos inscripciones concurrentes del mismo estudiante
2. Validación en frontend que no se replica en backend
3. Race condition al verificar profesor duplicado

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Implementar validaciones en Domain Service (única fuente de verdad) | Dev Senior | Sprint 1 |
| Usar transacciones con nivel de aislamiento Serializable | Dev Senior | Sprint 1 |
| Tests de concurrencia con múltiples threads | QA | Sprint 1 |
| Lock optimista con RowVersion en Enrollment | Dev | Sprint 1 |

**Código de Mitigación:**
```csharp
// Transacción con locking
await using var transaction = await _context.Database
    .BeginTransactionAsync(IsolationLevel.Serializable);

var student = await _context.Students
    .Include(s => s.Enrollments)
    .ThenInclude(e => e.Subject)
    .FirstOrDefaultAsync(s => s.Id == command.StudentId);

// Validaciones en dominio
_enrollmentService.ValidateEnrollment(student, subject);

await _context.SaveChangesAsync();
await transaction.CommitAsync();
```

---

### RT-002: Integración Frontend-Backend (GraphQL)

| Atributo | Valor |
|----------|-------|
| **ID** | RT-002 |
| **Categoría** | Integración |
| **Probabilidad** | Media (2) |
| **Impacto** | Alto (3) |
| **Score** | **6 - Crítico** |

**Descripción:**
GraphQL introduce complejidad adicional en la integración. Errores en el esquema, types incorrectos o problemas de N+1 queries pueden afectar rendimiento y desarrollo.

**Escenarios de Riesgo:**
1. Mismatch entre schema GraphQL y DTOs
2. N+1 queries sin DataLoaders
3. Errores de tipos en Apollo Angular
4. Over-fetching o under-fetching de datos

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Generar tipos TypeScript desde schema (codegen) | Dev Frontend | Sprint 1 |
| Implementar DataLoaders para todas las relaciones | Dev Backend | Sprint 1 |
| Configurar GraphQL Voyager para visualizar schema | Dev | Sprint 1 |
| Tests de integración GraphQL con Banana Cake Pop | QA | Sprint 1 |

**Configuración DataLoader:**
```csharp
// DataLoader para evitar N+1
public class SubjectByIdDataLoader : BatchDataLoader<int, Subject>
{
    protected override async Task<IReadOnlyDictionary<int, Subject>> LoadBatchAsync(
        IReadOnlyList<int> keys, CancellationToken ct)
    {
        return await _context.Subjects
            .Where(s => keys.Contains(s.Id))
            .ToDictionaryAsync(s => s.Id, ct);
    }
}
```

---

### RT-003: Manejo de Concurrencia

| Atributo | Valor |
|----------|-------|
| **ID** | RT-003 |
| **Categoría** | Arquitectura |
| **Probabilidad** | Media (2) |
| **Impacto** | Alto (3) |
| **Score** | **6 - Crítico** |

**Descripción:**
Múltiples usuarios podrían intentar inscribirse en la misma materia simultáneamente, generando conflictos o violaciones de reglas de negocio.

**Escenarios de Riesgo:**
1. Dos estudiantes inscriben la última plaza disponible
2. Estudiante inscribe 4ta materia por request concurrente
3. Datos obsoletos en UI mientras otro usuario modifica

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Implementar Optimistic Concurrency (RowVersion) | Dev Backend | Sprint 1 |
| Revalidar en backend siempre (no confiar en frontend) | Dev Backend | Sprint 1 |
| Mostrar toast de "datos actualizados" en conflictos | Dev Frontend | Sprint 2 |
| Tests de stress con k6 | QA | Sprint 2 |

**Implementación:**
```csharp
// Entidad con concurrencia optimista
public class Student
{
    [Timestamp]
    public byte[] RowVersion { get; set; }
}

// Manejo de conflicto
catch (DbUpdateConcurrencyException)
{
    return Result.Failure("CONCURRENT_MODIFICATION");
}
```

---

### RT-004: Rendimiento de Consultas Anidadas

| Atributo | Valor |
|----------|-------|
| **ID** | RT-004 |
| **Categoría** | Rendimiento |
| **Probabilidad** | Media (2) |
| **Impacto** | Medio (2) |
| **Score** | **4 - Moderado** |

**Descripción:**
Consultas GraphQL anidadas (estudiantes → inscripciones → materias → profesores) pueden generar queries pesadas si no se optimizan.

**Escenarios de Riesgo:**
1. Query de todos los estudiantes con todas sus relaciones
2. Timeouts en consultas sin límite de profundidad
3. Consumo excesivo de memoria en serialización

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Configurar límite de profundidad en HotChocolate (max 5) | Dev Backend | Sprint 1 |
| Implementar paginación en queries de listas | Dev Backend | Sprint 1 |
| Indexar campos de búsqueda (Email, ProfessorId) | DBA | Sprint 1 |
| Query complexity analyzer | Dev Backend | Sprint 2 |

**Configuración:**
```csharp
services.AddGraphQLServer()
    .SetMaxAllowedExecutionDepth(5)
    .SetPagingOptions(new PagingOptions
    {
        MaxPageSize = 50,
        DefaultPageSize = 20
    });
```

---

### RT-005: Curva de Aprendizaje del Stack

| Atributo | Valor |
|----------|-------|
| **ID** | RT-005 |
| **Categoría** | Equipo |
| **Probabilidad** | Alta (3) |
| **Impacto** | Bajo (1) |
| **Score** | **3 - Moderado** |

**Descripción:**
El stack incluye tecnologías relativamente nuevas (HotChocolate, Angular Signals, Apollo Angular) que pueden requerir tiempo de aprendizaje.

**Tecnologías con Curva:**
- HotChocolate (GraphQL .NET)
- Mapster (alternativa a AutoMapper)
- Angular Signals
- Apollo Angular

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Documentar patrones y ejemplos en wiki | Tech Lead | Sprint 1 |
| Code reviews detallados en PRs | Senior Dev | Continuo |
| Spike técnico para DataLoaders | Dev Backend | Sprint 1 |
| Usar generador de código Apollo | Dev Frontend | Sprint 1 |

---

### RT-006: Seguridad en GraphQL

| Atributo | Valor |
|----------|-------|
| **ID** | RT-006 |
| **Categoría** | Seguridad |
| **Probabilidad** | Baja (1) |
| **Impacto** | Alto (3) |
| **Score** | **3 - Moderado** |

**Descripción:**
GraphQL expone un endpoint flexible que puede ser abusado con queries maliciosas (deeply nested, introspection en prod, DoS).

**Escenarios de Riesgo:**
1. Query extremadamente anidada consume recursos
2. Introspection expone schema sensible
3. Mutation masiva sin rate limiting

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Deshabilitar introspection en producción | DevOps | Deploy |
| Configurar query complexity limits | Dev Backend | Sprint 1 |
| Rate limiting por IP (10 req/s) | DevOps | Sprint 2 |
| Persisted queries en producción | Dev Backend | Sprint 3 |

**Configuración:**
```csharp
services.AddGraphQLServer()
    .AddMaxComplexityRule(100)  // Límite de complejidad
    .AddMaxExecutionDepthRule(5)
    .ModifyOptions(o =>
    {
        // Deshabilitar introspection en prod
        if (!env.IsDevelopment())
            o.EnableSchemaIntrospection = false;
    });
```

---

### RT-007: Migración y Seeding de Datos

| Atributo | Valor |
|----------|-------|
| **ID** | RT-007 |
| **Categoría** | Base de Datos |
| **Probabilidad** | Baja (1) |
| **Impacto** | Medio (2) |
| **Score** | **2 - Bajo** |

**Descripción:**
Los datos iniciales (5 profesores, 10 materias) deben estar correctamente relacionados. Errores en seeding pueden romper reglas de negocio.

**Escenarios de Riesgo:**
1. Profesor asignado a más de 2 materias
2. IDs inconsistentes entre migraciones
3. Datos duplicados en re-ejecución de seed

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Seeding idempotente (verificar existencia) | Dev Backend | Sprint 1 |
| Validación post-seed en tests | QA | Sprint 1 |
| Script de verificación de integridad | DBA | Sprint 1 |

---

### RT-008: Testing de Reglas de Negocio

| Atributo | Valor |
|----------|-------|
| **ID** | RT-008 |
| **Categoría** | Calidad |
| **Probabilidad** | Media (2) |
| **Impacto** | Medio (2) |
| **Score** | **4 - Moderado** |

**Descripción:**
Las reglas de negocio complejas requieren cobertura exhaustiva de tests. Casos edge pueden quedar sin probar.

**Casos Edge Críticos:**
1. Inscribir materia 3 cuando ya tiene 2 del mismo "tipo"
2. Cancelar inscripción y re-inscribir rápidamente
3. Estudiante con 3 materias intenta cambiar una

**Estrategia de Mitigación:**

| Acción | Responsable | Plazo |
|--------|-------------|-------|
| Property-based testing para combinaciones | QA | Sprint 1 |
| Matriz de casos de prueba exhaustiva | QA | Sprint 1 |
| Mutation testing (Stryker) | QA | Sprint 2 |

---

## 4. Matriz de Riesgos Consolidada

| ID | Riesgo | Prob | Impacto | Score | Prioridad |
|----|--------|------|---------|-------|-----------|
| RT-001 | Validaciones cruzadas | 3 | 3 | **9** | 1 |
| RT-002 | Integración GraphQL | 2 | 3 | **6** | 2 |
| RT-003 | Concurrencia | 2 | 3 | **6** | 3 |
| RT-004 | Rendimiento queries | 2 | 2 | 4 | 4 |
| RT-005 | Curva aprendizaje | 3 | 1 | 3 | 5 |
| RT-006 | Seguridad GraphQL | 1 | 3 | 3 | 6 |
| RT-008 | Testing reglas | 2 | 2 | 4 | 7 |
| RT-007 | Seeding datos | 1 | 2 | 2 | 8 |

---

## 5. Plan de Contingencia

### Si RT-001 se materializa (validaciones fallan):
1. Rollback a versión anterior
2. Fix inmediato en Domain Service
3. Agregar tests de regresión
4. Re-deploy con verificación manual

### Si RT-002 se materializa (integración falla):
1. Fallback a REST API simple
2. Schema manual sin codegen
3. Simplificar queries GraphQL

### Si RT-003 se materializa (race conditions):
1. Lock pesimista temporal
2. Queue de inscripciones
3. Revisión manual de conflictos

---

## 6. Indicadores de Monitoreo

| Riesgo | Indicador | Umbral de Alerta |
|--------|-----------|------------------|
| RT-001 | Inscripciones fallidas por validación | > 5% |
| RT-002 | Errores GraphQL 500 | > 1% |
| RT-003 | DbUpdateConcurrencyException | > 10/hora |
| RT-004 | Query time P95 | > 500ms |
| RT-006 | Requests bloqueados por rate limit | > 100/hora |

---

## 7. Revisión de Riesgos

| Fecha | Revisor | Acción |
|-------|---------|--------|
| Sprint 1 Review | Tech Lead | Evaluar RT-001, RT-002 |
| Sprint 2 Review | Tech Lead | Evaluar RT-003, RT-004 |
| Pre-deploy | QA Lead | Validar mitigaciones |

---

## 8. Aprobación

| Rol | Nombre | Fecha | Firma |
|-----|--------|-------|-------|
| Líder Técnico | Sistema | 2026-01-07 | ✓ |
| Arquitecto | Pendiente | - | - |
| Project Manager | Pendiente | - | - |
