401 lines
12 KiB
Markdown
401 lines
12 KiB
Markdown
# 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 | - | - |
|