# Migration TODO — Sprint 5 Día 0 → Día 5

Pendientes identificados durante la migración inicial desde `02_AREAS/02_CIVIL/02_HERRAMIENTAS/`.

## ✅ Completado Día 0 (2026-05-13)

- Archivos backend copiados: `servidor_local.py`, `db_loader.py`, `login.html`, `dashboard.html` (renombrado), `ergon_favicon.svg`, `db/` (sin blobs ni ergon.db)
- Sanitización UI-facing: 0 ocurrencias de Fortaleza/Carmelitas/Hoppe/Vicente/DG_Civil/Torres DG en archivos publicos
- Patch `PORT` desde env (`int(os.environ.get("PORT", 8080))`) para Railway
- Patch rename interno `PROTOTIPO_ERGON_v2.html` → `dashboard.html`
- Endpoint `/health` agregado para healthcheck Railway
- Dockerfile actualizado: HEALTHCHECK + CMD `python servidor_local.py` (sin waitress, mantener stdlib http.server hasta Sprint 6)

## ⏳ Día 1 (jue 14/05)

### 1. Variables de entorno
- [ ] Leer `.env.local` con `python-dotenv` al arranque de `servidor_local.py`
- [ ] Variables esperadas en Railway env:
  - `ANTHROPIC_API_KEY` (key dedicada `ergonpy-prod-2026-05`)
  - `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY`, `SUPABASE_JWT_SECRET`
  - `DATABASE_PATH=/data/ergon.db`
  - `BLOBS_DIR=/data/blobs`, `DOCS_DIR=/data/docs`
  - `ALLOWED_ORIGINS=https://ergonpy.com,https://app.ergonpy.com`
  - `SECURE_COOKIES=true`
  - `MAX_TOKENS_PER_USER_MONTH=50000`

### 2. CORS production
- [ ] `_write_cors_headers` debe leer `ALLOWED_ORIGINS` env var en lugar de wildcard
- [ ] Match exacto contra Origin header del request
- [ ] `Access-Control-Allow-Credentials: true` mantener para cookies

### 3. Cookies HTTPS
- [ ] `Set-Cookie` con flag `Secure` cuando `SECURE_COOKIES=true`
- [ ] `SameSite=Lax` mantener
- [ ] Cookie `ergon_session` sigue HttpOnly

### 4. Inicialización DB en first-boot Railway
- [ ] `servidor_local.py` al arranque: verificar si `/data/ergon.db` existe, si no, correr `db/init_db.py` + seed minimo (admin user + obra demo `EESS01`)
- [ ] Seed específico para JB: 1 obra ficticia "Estación Demo" con 4 rubros típicos de estaciones de servicio (demolición / fundación / losa / instalaciones combustible)

## ⏳ Día 2 (vie 15/05) - Supabase Auth bridge

### 5. Migración `migrate_supabase_bridge.py`
- [ ] Agregar columna `supabase_uid TEXT UNIQUE NULL` a tabla `usuarios`
- [ ] Crear tabla `supabase_jwt_blacklist` (token, exp, revoked_at) para logout server-side
- [ ] Index `idx_usuarios_supabase_uid`

### 6. `_require_session()` extendido en `servidor_local.py`
- [ ] Aceptar 2 mecanismos en paralelo:
  1. Cookie `ergon_session` bcrypt legacy (admin@demo.local, etc)
  2. Authorization header `Bearer <jwt>` validado contra `SUPABASE_JWT_SECRET` con PyJWT
- [ ] Si JWT válido: lookup/insert en `usuarios` por `supabase_uid`, retornar session dict standard
- [ ] Si JWT inválido: 401

### 7. Endpoints nuevos auth
- [ ] `POST /api/auth/supabase-sync` — recibe JWT, crea/actualiza fila en `usuarios` con `supabase_uid`, retorna user data
- [ ] Webhook Supabase → backend cuando usuario se registra (opcional Sprint 6)

## ⏳ Día 3+ (sáb-lun)

### 8. Sanitización profunda backend
Las siguientes ocurrencias quedan en archivos no UI-facing pero sería bueno limpiar:
- [ ] `db/smoke_test_f10.py:166,170` — patterns prohibidos del test (LEGITIMO, NO TOCAR — el test verifica que no aparezcan)
- [ ] PDF generation: si en Sprint 6 se trae `generate_informe_ergon.py`, sanitizar referencias a "DG" / "Hoppe" en headers/footers
- [ ] Eliminar import paths que apunten a `02_AREAS/02_CIVIL/02_HERRAMIENTAS` (no aplica al backend actual, verificar)

### 9. Rate limit
- [ ] Middleware simple en `servidor_local.py`: dict en memoria con `{ip+endpoint: [timestamps]}`, cap 60 req/min por (IP, endpoint)
- [ ] Por usuario autenticado: cap `MAX_TOKENS_PER_USER_MONTH` Anthropic tokens. Tabla `usuarios_token_budget` (usuario_id, mes_iso, tokens_used)

### 10. Trial flow
- [ ] Columna `usuarios.trial_ends_at` (default now() + 14 días en signup)
- [ ] Watermark "DEMO" en headers de exports Excel cuando `trial_ends_at > now()`
- [ ] Bloqueo soft de uploads cuando trial expirado (banner CTA upgrade)

## ❌ NO migrar / NO traer al backend en Sprint 5

- `ergon_latex/` — Sprint 4.1 bloqueado por feedback Victor sobre densidad v4 vs v1
- `ergon_charts.py`, `generate_informe_ergon.py`, `generate_informe_ergon_docx.py`, `ergon_brand_reportlab.py` — generación PDF, Sprint 6
- `generate_dg_civil.py` — necesita renombrado profundo + sanitización, Sprint 6
- `convert_skp_to_glb.py` + `blender/` — visor 3D feature secundaria, Sprint 6+
- `backgrounds/`, `factibilidad/`, `_archivo_confidencial_hoppe/` — contenido DG no transferible
- `logo_dg_*.png` — branding DG no transferible
- `*.xlsx`, `consultas_log.csv` — data demo / logs legacy

## Verificaciones automáticas

```bash
# Después de cada round de sanitización
cd /d/ergonpy/ergonpy-backend
grep -rcE "Fortaleza|Carmelitas|Hoppe|Vicente|DG[_ ]?Civil|Torres DG" \
  --include="*.py" --include="*.html" --include="*.sql" \
  . | grep -v ":0$" || echo "LIMPIO"

# Smoke test pre-deploy Railway
python servidor_local.py &
SERVER_PID=$!
sleep 2
curl -f http://localhost:8080/health || (kill $SERVER_PID; echo "HEALTH FAIL"; exit 1)
kill $SERVER_PID
```
