# Security — Centro de Mando (app.4ventures.es) ## Incident NOW (secretos filtrados) El PDF “Agencia 2030” y el antiguo `.env.example` del repo contenían **JWTs reales** (anon + service_role) y passwords de demo. ### Rotación (checklist — hacerlo en ventana corta) 1. Supabase Studio → Settings → API → **regenerar** `anon` y `service_role` **o** (self-hosted) cambiar `JWT_SECRET` / `GOTRUE_JWT_SECRET` y emitir JWTs nuevos. 2. Dokploy → client-portal Environment: pegar anon + service_role nuevos → Save → Deploy. 3. n8n (credenciales Supabase / HTTP headers): actualizar API keys. 4. Local: actualizar `.env.local` (gitignored); no tocar `.env.example` (placeholders). 5. Invalidar sesiones: Auth → Users → sign-out / cambiar password `marketing@4ventures.es` si hubo leak de demo. 6. Smoke: `curl /api/health` → `serviceRoleConfigured true`; `python3 scripts/smoke_operator_login.py`. 7. Rotar `ANTHROPIC_API_KEY` si estuvo en chats/docs (opcional, independiente). **Estado 2026-09-21:** claves nuevas **preparadas** en `.ops/supabase_rotated.env` (gitignored). **Aplicación bloqueada:** el stack vivo (`ventures-web-supabase-gm0nnn-*`) no tiene compose editable en Dokploy (`4ventures-infra` está en `error` / `composeFile` vacío) y SSH al VPS (`187.77.170.176:22`) hace timeout. Sin recrear contenedores con el nuevo `JWT_SECRET`, los JWT filtrados **siguen válidos**. **Desbloqueo:** acceso host (SSH/VPN) o restaurar el compose Supabase en Dokploy → sustituir env → recrear servicios auth/kong/rest/studio → Deploy client-portal. ## Superficies a restringir (amenaza) | Host | Acción | |------|--------| | `git.4ventures.es` | VPN / IP allowlist / Basic Auth delante de Gitea | | `n8n-agencia` UI | No público; solo webhooks con path secreto | | `supabase` Studio | Solo red interna / SSO admin | | `app` | Público OK; APIs tras sesión (middleware) | Patch Traefik **aplicado** 2026-09-21 (ver `.ops/HARDEN_SURFACES.md`). Allowlist oficina: `90.161.248.78/32` — UI git/n8n; webhooks abiertos. Si el ISP cambia la IP, actualizar middleware `office-allowlist`. ## Controles en código (este repo) - Middleware exige sesión en `/dashboard/*` y `/api/*` (excepto `/api/health`). - `/api/chat` y `/api/simulate` exigen usuario + `tenant_id` en metadata. - `/api/admin/*` bloqueado para rol `client`. - Activos leen `documents` vía cliente SSR (RLS), no anon global. - Headers: frame deny, nosniff, robots noindex, HSTS en prod. ## RLS (verificar en Studio) Ejecutar checklist en `sql/rls_checklist.sql`. Sin RLS real, el multi-tenant es cosmético. ## Cron / n8n - Webhooks solo POST. - Header secreto compartido (`X-Webhook-Secret` / HMAC) en lead-inbound y deal-won. - No loguear bodies con PII a stdout público.