Secretos fuera del repositorio
Credenciales, tokens, llaves privadas y archivos .env se administran por variables de entorno y nunca se versionan.
Plataforma técnica · Seguridad
Seguridad
Las buenas prácticas de seguridad son criterios de aceptación para desarrollo. Cada endpoint, servicio o migración debe declarar cómo autentica, autoriza, valida datos, preserva tenant scope y evita exposición de información sensible.
Secretos fuera del repositorio
Credenciales, tokens, llaves privadas y archivos .env se administran por variables de entorno y nunca se versionan.
Entrada validada
Todo payload externo se valida con express-validator, esquema dedicado o validación equivalente antes de invocar servicios.
SQL parametrizado
Las consultas usan parámetros ($1, $2) o builders compartidos. No se concatenan entradas de usuario en SQL.
Logs mínimos
Los logs deben explicar el fallo sin incluir contraseñas, tokens, RUT reales, remuneraciones ni datos financieros críticos.
| Área | Criterio de aceptación |
|---|---|
| Autenticación | Toda ruta protegida usa authenticateToken antes del handler |
| Autorización | Operaciones sensibles usan authorizeRoute, requireRole o regla funcional explícita |
| Tenant scope | La ruta resuelve tenant desde usuario o contexto autorizado; no confía en tenant_id arbitrario |
| Validación | Query, params y body rechazan tipos inválidos, campos faltantes y rangos fuera de contrato |
| SQL | No existe interpolación de entradas externas dentro de strings SQL |
| Auditoría | Mutaciones críticas registran evento o quedan cubiertas por auditMiddleware |
| Datos sensibles | Ejemplos, fixtures, logs y errores usan placeholders o valores redactados |
| Errores | Las respuestas no revelan stack traces, secretos ni estructura interna innecesaria |
| Dependencias | Cambios de paquetes pasan por revisión y no introducen vulnerabilidades críticas conocidas |
authenticateToken a nivel de router o ruta individual.requireRole o authorizeRoute cuando la operación no sea lectura básica.params, query y body antes de construir comandos de dominio.req.user o desde un helper autorizado.router.use(authenticateToken);
router.post( '/', requireRole(['ADMIN', 'SUPER_ADMIN']), [ body('name').isString().trim().notEmpty(), body('status').optional().isBoolean(), ], async (req: AuthenticatedRequest, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, error: 'Validation Error', errors: errors.array(), }); }
const result = await service.create({ tenantId: req.user?.tenantId, input: req.body, });
return res.status(201).json({ success: true, data: result }); },);| Caso | Respuesta esperada |
|---|---|
| Sin token | 401 con error genérico de autenticación |
| Sesión vencida o revocada | 401, limpieza de cookie y mensaje sin detalles internos |
| Rol insuficiente | 403 con recurso o rol requerido solo si no expone información sensible |
| Entrada inválida | 400 con errores de validación controlados |
| Error de dominio | Código específico del dominio sin stack trace |
| Error inesperado | 500 genérico y detalle solo en logs internos sanitizados |
Antes de cerrar un cambio, revisar explícitamente:
| Tipo de dato | Acción esperada |
|---|---|
| Contraseñas y tokens | Nunca se retornan, registran ni guardan en texto plano |
| RUT y datos personales | Se usan placeholders en documentación y fixtures |
| Remuneraciones | Se tratan como dato crítico y no se exponen en logs |
| Reportes financieros | Se protegen con rol, tenant scope y auditoría |
| Exportaciones | Se registran como evento auditable cuando contienen datos confidenciales |