cambios para worker-remoto

This commit is contained in:
lordpietre 2026-04-01 21:29:11 +00:00
parent 98e0cd0e46
commit be56de7dd4
19 changed files with 1544 additions and 216 deletions

448
bugs.md Normal file
View file

@ -0,0 +1,448 @@
# Análisis de Errores e Inconsistencias - RSS2
Fecha de análisis: 2026-04-01
---
## Resumen Ejecutivo
Se han identificado **13 problemas** clasificados en:
- 3 Errores Críticos
- 7 Inconsistencias
- 3 Warnings de Arquitectura
---
## 1. Errores Críticos
### 1.1 Rate Limiting No Implementado
**Ubicación:** `backend/internal/middleware/auth.go:104-108`
**Descripción:**
La función existe pero no hace nada:
```go
func RateLimitMiddleware(requestsPerMinute int) gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
}
}
```
**Problema:**
No implementa ningún tipo de limitación de rate. Vulnerable a ataques de fuerza bruta y DoS.
**Impacto:** Alto - Seguridad comprometida.
---
### 1.2 CORS Demasiado Permisivo
**Ubicación:** `backend/internal/middleware/auth.go:77-90`
**Descripción:**
```go
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
```
**Problema:**
Permite cualquier origen, lo cual es inseguro para APIs de producción. Permite ataques CSRF y expone datos a orígenes maliciosos.
**Impacto:** Alto - Seguridad comprometida.
---
### 1.3 Secret Key Por Defecto Hardcodeada
**Ubicación:** `backend/internal/config/config.go:32`
**Descripción:**
```go
SecretKey: getEnv("SECRET_KEY", "change-this-secret-key"),
```
**Problema:**
Si no se proporciona la variable de entorno, la aplicación usa una clave por defecto conocida. Cualquier despliegue sin configurar esta variable es vulnerable.
**Impacto:** Crítico - Compromiso total de autenticación.
---
## 2. Inconsistencias
### 2.1 Mapeo de Campos Inconsistente (Snake Case vs Camel Case)
**Descripción:**
La aplicación usa convenciones de nomenclatura diferentes en distintas capas:
| Capa | Estructura | Ejemplo |
|------|------------|---------|
| Models | Snake case | `Title`, `Summary`, `ImageURL` |
| Handlers | Pascal case | `Titulo`, `Resumen`, `ImagenURL` |
| Frontend TS | camelCase | `titulo`, `resumen`, `imagen_url` |
**Archivos afectados:**
- `backend/internal/models/models.go:7-19`
- `backend/internal/handlers/news.go:14-28`
- `frontend/src/services/api.ts:20-34`
**Problema:**
Dificulta el mantenimiento y genera potenciales errores de serialización.
---
### 2.2 Idioma de Traducción Hardcodeado
**Descripción:**
El idioma destino de traducción (`es`) está hardcodeado en múltiples lugares:
**news.go:67:**
```go
where += " AND t.status = 'done' AND t.titulo_trad IS NOT NULL"
```
**news.go:96:**
```go
LEFT JOIN traducciones t ON t.noticia_id = n.id AND t.lang_to = 'es'
```
**search.go:34-37:**
```go
if lang == "" {
lang = "es"
}
```
**Problema:**
No es configurable. Si se quiere traducir a otros idiomas, requiere cambios en múltiples archivos.
---
### 2.3 Columna `role` en Users Sin映射 en Modelo
**Descripción:**
Se añade una columna `role` a la tabla users:
**cmd/server/main.go:41-48:**
```go
_, err = db.GetPool().Exec(ctx, `
ALTER TABLE users ADD COLUMN IF NOT EXISTS role VARCHAR(20) DEFAULT 'user'
`)
```
**Pero el modelo User no tiene este campo:**
**models/models.go:86-94:**
```go
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
Username string `json:"username"`
PasswordHash string `json:"-"`
IsAdmin bool `json:"is_admin"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
```
**Problema:**
La columna `role` nunca se usa realmente. Hay dos campos (`role` y `is_admin`) que pueden causar confusión.
---
### 2.4 Feature No Implementada en Discovery
**Ubicación:** `backend/cmd/discovery/main.go:129-133`
**Descripción:**
```go
func findFeedLinksInHTML(baseURL string) ([]string, error) {
// Simple feed link finder - returns empty for now
// In production, use goquery to parse HTML and find RSS/Atom links
return []string{}, nil
}
```
**Problema:**
El worker de discovery no puede encontrar feeds RSS embebidos en páginas HTML. Solo detecta feeds directos.
**Impacto:** Medio - Reduce la efectividad del descubrimiento de feeds.
---
### 2.5 LoggerMiddleware No Funcional
**Ubicación:** `backend/internal/middleware/auth.go:93-101`
**Descripción:**
```go
func LoggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
status := c.Writer.Status()
if status >= 400 {
// Log error responses - pero no hace nada!
}
}
}
```
**Problema:**
El logging de errores está commented out. No se registra nada.
---
### 2.6 Columnas de BD Diferentes a Modelos
**Descripción:**
El handler `search.go` referencia columnas que no existen en los modelos:
**search.go:91-92:**
```go
SELECT n.id, n.titulo, n.resumen, n.contenido, n.url, n.imagen,
n.feed_id, n.lang, n.categoria_id, n.pais_id, n.created_at, n.updated_at,
```
**Pero en models.go:7-19:**
```go
type News struct {
ID int64 `json:"id"`
Title string `json:"title"`
Summary string `json:"summary"`
Content string `json:"content"`
URL string `json:"url"`
ImageURL *string `json:"image_url"`
PublishedAt *time.Time `json:"published_at"`
Lang string `json:"lang"`
FeedID int64 `json:"feed_id"`
...
}
```
**Problema:**
- Modelo usa `Title`, BD usa `titulo`
- Modelo usa `Summary`, BD usa `resumen`
- Modelo usa `ImageURL`, BD usa `imagen`
- Modelo usa `PublishedAt`, BD usa `fecha`
Esto causa errores de serialización potenciales.
---
### 2.7 Inicialización de Base de Datos Duplicada
**Descripción:**
Existen dos formas de conectar a la base de datos:
1. `db.Connect()` en `backend/internal/db/postgres.go:13`
2. `workers.Connect()` en `backend/internal/workers/db.go`
**Problema:**
Códigos duplicados que mantienen conexiones separadas. Puede causar problemas de pool de conexiones.
---
## 3. Warnings de Arquitectura
### 3.1 Creación de Tablas en Runtime
**Ubicación:** `backend/cmd/server/main.go:20-77`
**Descripción:**
En lugar de usar migraciones formales, el servidor crea tablas al iniciar:
```go
func initDB() {
_, err := db.GetPool().Exec(ctx, `
CREATE TABLE IF NOT EXISTS entity_aliases (...)
`)
// más tablas...
}
```
**Problema:**
- No hay control de versiones
- No hay rollback
- Difícil de mantener en producción
**Recomendación:** Usar golang-migrate o similar.
---
### 3.2 No Hay Tests Unitarios
**Descripción:**
No se encontraron archivos `*_test.go` en el código backend.
**Problema:**
Sin tests, cualquier cambio puede romper funcionalidad existente sin detección.
---
### 3.3 Pool de Conexiones Sin Validación Periódica
**Ubicación:** `backend/internal/db/postgres.go`
**Descripción:**
El pool se crea pero no hay health check periódico.
**Problema:**
Las conexiones zombie pueden acumularse sin detección.
---
## 4. Recomendaciones de Corrección
### Alta Prioridad
1. **Unificar JWT Secret:** Usar un único package para manejar el secret
2. **Implementar Rate Limiting:** Usar una librería como `golang.org/x/time/rate`
3. **Configurar CORS correctamente:** Usar variable de entorno para orígenes permitidos
4. **Forzar Secret Key:** Hacer requerida la variable `SECRET_KEY`
### Media Prioridad
5. **Traducir idioma configurable:** Pasar idioma como parámetro o configuración
6. **Usar migraciones:** Implementar golang-migrate
7. **Añadir tests:** Crear tests unitarios para handlers críticos
8. **Corregir mapeo de campos:** Estandarizar snake_case en toda la aplicación
### Baja Prioridad
9. **Implementar LoggerMiddleware:** Añadir logging real
10. **Implementar findFeedLinksInHTML:** Usar goquery para parsing HTML
11. **Consolidar DB:** Unificar inicialización de base de datos
---
## 5. Estadísticas
| Tipo | Cantidad |
|------|----------|
| Errores Críticos | 3 |
| Inconsistencias | 7 |
| Warnings | 3 |
| **Total** | **13** |
---
## 6. Problemas Adicionales Detectados
### 6.1 Mapeo de Campos Inconsistente (Frontend)
**Descripción:** El frontend usa `snake_case` pero los modelos Go usan `PascalCase`.
**Archivos:**
- `frontend/src/services/api.ts` - usa `titulo`, `resumen`
- `backend/internal/models/models.go` - usa `Title`, `Summary`
---
### 6.2 Structs Duplicados para Mismo Recurso
**Descripción:** `handlers/news.go` define `NewsResponse` diferente a `models/models.go:News`.
---
### 6.3 Query Params Inconsistentes
**Descripción:** Algunos handlers usan `category_id` (inglés) y otros `categoria_id` (español).
---
### 6.4 Duplicación Config DB
**Descripción:** API usa `DATABASE_URL`, workers usan `DB_HOST`, `DB_PORT`, etc.
---
### 6.5 Sin Health Checks en Workers
**Descripción:** Workers no implementan endpoint `/health`.
---
### 6.6 Manejo de Errores Inconsistente
**Descripción:** Mezcla de `gin.H{"error": ...}` y `models.ErrorResponse`.
---
## 7. Errores y Problemas Críticos Detectados
### 7.1 ~~Errores Ignorados Silenciosamente~~ **(RESUELTO)**
**Descripción:** Múltiples lugares donde errores eran ignorados sin logging.
**Ejemplos corregidos:**
- `admin.go:488-492` - Ahora verifica errores de `db.GetPool().Exec()`
- `admin.go:522` - Verifica error al actualizar estado
**Impacto:** Fallos silenciosos que pasan desapercibidos.
---
### 7.2 ~~Rutas Hardcodeadas~~ **(RESUELTO)**
**Descripción:** Rutas de archivos hardcodeadas en el código.
**Correcciones:**
- `admin.go:469,474,509` - Ahora usa `config.Load().DockerComposeDir`
- `server/main.go:113` - Ahora usa `cfg.WikiImagesPath`
- Añadidos nuevos campos en config: `DockerComposeDir`, `WikiImagesPath`
---
## 7.3 Secret Key Por Defecto
**Descripción:** `config.go:32` usa clave por defecto known.
```go
SecretKey: getEnv("SECRET_KEY", "change-this-secret-key")
```
**Impacto:** Medio - Si no se configura, usar clave insegura.
---
### 7.4 Rate Limiting No Implementado
**Descripción:** `middleware/auth.go:104-108` tiene función vacía.
**Impacto:** Alto - Vulnerable a ataques de fuerza bruta.
---
### 7.5 CORS Demasiado Permisivo
**Descripción:** `middleware/auth.go:79` permite cualquier origen.
**Impacto:** Alto - Expuesto a ataques CSRF.
---
## 8. Recomendaciones de Corrección (Actualizado)
### Alta Prioridad (CRÍTICO)
1. ~~Unificar JWT Secret~~
2. Implementar Rate Limiting
3. ~~**Configurar CORS correctamente:** Usar variable de entorno~~
4. ~~**Corregir manejo de errores:** No ignorar silenciosamente~~
5. ~~**Eliminar rutas hardcodeadas**~~
### Media Prioridad
7. Idioma traducciones configurable
8. Usar migraciones
9. Añadir tests
10. Corregir mapeo de campos
### Baja Prioridad
11. Implementar LoggerMiddleware
12. Implementar findFeedLinksInHTML
13. Consolidar DB
14. Estandarizar respuestas API
15. Añadir health checks