# 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 { protected override async Task> LoadBatchAsync( IReadOnlyList 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 | - | - |