academia/docs/entregables/01-analisis/riesgos/AN-005-riesgos-tecnicos.md

401 lines
12 KiB
Markdown
Raw Permalink Normal View History

# 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 | - | - |