11 — Privacidad y seguridad — SURCO
1. Contexto
SURCO es un demo de portfolio / vertical slice de cuaderno de campo.
Trata datos de cuenta y notas operativas de finca. No es un producto certificado en producción, pero el diseño aplica controles mínimos serios (JWT, bcrypt, autorización por rol).
No se declara cumplimiento RGPD/LOPDGDD definitivo: en producción real se requieren política de privacidad, base legal documentada y, si hay encargados, DPA.
2. Datos tratados
| Dato | Categoría | Finalidad | Sensibilidad |
|---|---|---|---|
| Identificador cuenta | Login | Personal | |
| passwordHash | Credencial | Auth (nunca password en claro) | Crítico |
| name | Identidad | UI personalizada | Personal |
| role | Autorización | Permisos | Operativo |
| parcel name, crop, ha | Datos explotación | Contexto de tarea | Operativo |
| task title, notes, dueAt, status, code | Operativa | Cuaderno | Operativo (notes = texto libre) |
| technicianId / farmerId | Relacional | Asignación | Operativo |
No se tratan en v1: ubicación GPS, biometría, datos de salud personal, pagos, documentos de identidad, geolocalización de parcelas.
3. Base legítima (modelo producto real)
Si SURCO fuera producción en UE:
| Tratamiento | Base (orientativa) |
|---|---|
| Cuenta de usuario | Ejecución de contrato / medidas precontractuales |
| Logs técnicos | Interés legítimo seguridad |
| Notas de parcela | Ejecución del servicio |
Demo: datos seed ficticios; no usar emails reales de terceros sin consentimiento.
4. Controles de seguridad
| Control | Implementación v1 |
|---|---|
| Hash de contraseña | bcrypt (seed cost 10) |
| Transporte | HTTPS en deploy; HTTP local dev |
| AuthN | JWT firmado (HS256) con secret de entorno |
| AuthZ | JwtAuthGuard + checks farmer/technician + FARMER-only create |
| Validación entrada | class-validator DTOs |
| Enum status | Solo valores TaskStatus |
| Secretos | .env / Neon URL fuera de git |
| Minimización | Sin campos PII extra; sin GPS ni fotos |
Matriz de autorización (resumen)
| Acción | FARMER | TECHNICIAN |
|---|---|---|
| Login | ✓ | ✓ |
| List own | ✓ | ✓ asignadas |
| Create | ✓ | ✗ 403 |
| Get if party | ✓ | ✓ |
| Patch status if party | ✓ | ✓ (subconjunto ACTIVE/DONE/CANCELLED) |
5. Amenazas y mitigaciones
| Amenaza | Riesgo | Mitigación |
|---|---|---|
| Credenciales demo públicas | Alto en prod real | Solo demo; rotar en prod |
| JWT robado (XSS) | Medio | No guardar datos sensibles extra; CSP futuro; HttpOnly cookie posible evolución |
| IDOR task id | Alto sin checks | get/update validan ownership |
| Enumeración de emails técnico | Bajo | 404 “Técnico no encontrado” |
| Fuerza bruta login | Medio | Rate limit futuro (no v1) |
| SQL injection | Bajo | Prisma parametrizado |
| Logs con passwords | Alto | No loguear body de login |
6. Retención y borrado (modelo / hipótesis de producto)
| Dato | Retención demo | Producción sugerida |
|---|---|---|
| Users seed | Mientras exista DB demo | Mientras cuenta activa |
| Tasks | Hasta delete manual / seed reset | p. ej. 24 meses post-cierre (propuesta) |
| Logs de acceso | N/A v1 | 90 días (propuesta) |
| JWT | Expiración secret-dependent | TTL corto + refresh |
v1 no expone endpoint de borrado de cuenta (fuera de alcance).
7. Cookies y tracking
- Auth en localStorage (token), no cookie de sesión.
- Sin banners de analytics de terceros en v1.
- Si se añade analytics (doc 12), minimización IP y consentimiento según base legal.
8. Roles y principio de mínimo privilegio
- TECHNICIAN no crea tareas ni ve tareas de otros farmers no asignadas.
- No hay rol ADMIN en v1 (reduce superficie).
- Parcelas solo del farmer propietario.
- Email de técnico opcional en create: único PII de “tercero” ligero en el flujo.
9. Incidentes (proceso demo)
- Rotar
JWT_SECRETy forzar re-login. - Reset seed / rotar passwords demo.
- Revisar logs Nest y Neon.
- Notificar usuarios afectados si hubiera PII real.
- Documentar en memory si afecta al caso.
10. Criterios de aceptación seguridad
- Password no se almacena en claro.
/api/taskssin Bearer → 401.- TECHNICIAN POST
/api/tasks→ 403. - TECHNICIAN GET tarea de otro → 403.
.envcon DATABASE_URL no versionado en repo público (revisar.gitignore).- No se loguean contraseñas ni tokens completos en cliente.