# Infraestructura — Overview

> Última actualización: 2026-04-28 (post-validación contra VPS reales)
> Estado: **Fase 1 (documentación) — relevamiento contra producción completado**

Este directorio consolida lo que vive *fuera del código de la app*: VPS, accesos, secretos, cronjobs, integraciones externas y procedimientos de recuperación. Convive con `infraestructura-operativa.md` (operativa de pipeline) y `guia-provisionado.md` (uso del comando `bewpro:new`); estos docs cubren el **plano de infraestructura** propiamente dicho.

## Índice

| Doc | Cubre |
|-----|-------|
| [00-overview.md](00-overview.md) | Este archivo. Topology resumida + índice + estado |
| [01-secrets-inventory.md](01-secrets-inventory.md) | Inventario de credenciales (sin valores) — qué/dónde/quién |
| [02-cronjobs.md](02-cronjobs.md) | Todos los cron en un solo lugar (Laravel scheduler + VPS1 + VPS2) |
| [03-runbook-recovery.md](03-runbook-recovery.md) | Qué hacer cuando algo se rompe |
| [04-risks-and-priorities.md](04-risks-and-priorities.md) | Riesgos identificados + plan de mitigación priorizado |
| [05-ssh-access-methodology.md](05-ssh-access-methodology.md) | Metodología de acceso SSH (propuesta — Fase 2) |

## Topology resumida

```
                 ┌──────────────────────────┐
                 │   bewpro.com (Laravel)   │
                 │   Stripe webhook entry   │
                 └──────────┬───────────────┘
                            │ Pipeline_Status="Required"
                            ▼
                 ┌──────────────────────────┐
                 │   Airtable                │
                 │   appRxvpzqCmNsw2JN      │
                 │   • Projects             │
                 │   • Subscriptions        │
                 │   • Shop Products + Copy │
                 └──────────┬───────────────┘
                            │ poll cada 5 min
                            ▼
                 ┌──────────────────────────┐
                 │   VPS1 — Hostinger        │
                 │   72.61.45.136 :22       │
                 │   ROL: orquestador       │
                 │   /root/scripts/         │
                 │     • process-airtable.sh│
                 │     • setup_cd_project*.sh│
                 │     • .airtable.env (creds)│
                 └──────────┬───────────────┘
                            │ select_target_server()
                  ┌─────────┴──────────┐
                  ▼                    ▼
          ┌───────────────┐    ┌───────────────┐
          │ VPS1 local    │    │ VPS2 Donweb   │
          │ ~36 cuentas   │    │ 179.43.124.219│
          │               │    │ :5633         │
          │               │    │ ~21 cuentas   │
          └───────────────┘    └───────────────┘
                            │
                            ▼
                 ┌──────────────────────────┐
                 │   Slack webhooks         │
                 │   7 canales              │
                 └──────────────────────────┘
```

## Componentes

| Componente | IP / Endpoint | Hostname | Rol | Tenants reales |
|---|---|---|---|---|
| **VPS1** Hostinger | 72.61.45.136 :22 | `srv1112606.hstgr.cloud` | Orquestador + hosting | **30** (validado 2026-04-28) |
| **VPS2** Donweb | 179.43.124.219 :22 + :5633 | `vps-5891588-x.dattaweb.com` | Hosting | **9** (validado 2026-04-28) |
| **Airtable** | appRxvpzqCmNsw2JN | Source of truth de billing y pipeline | Webhook Stripe, cron VPS1, comandos artisan |
| **Stripe** | api.stripe.com | Payments + suscripciones | Webhook → AirtableService |
| **Slack** | hooks.slack.com | 7 webhooks | SlackService desde Laravel + email pipe |
| **Hostinger DNS** | developers.hostinger.com | Zona bewpro.com | step 9 de setup script |
| **Cloudinary** | api.cloudinary.com | Asset storage por tenant | step 7 de provision |
| **Let's Encrypt** | (via cPanel AutoSSL) | SSL certs | step 10 de setup script |

## Cómo se relaciona con los otros docs

- **`../infraestructura-operativa.md`** — flujo operativo (pipeline Stripe→provisioning, billing, alertas Slack, market-ready). **Es la fuente de verdad funcional.**
- **`../guia-provisionado.md`** — uso del comando `bewpro:new` y resolución de cores.
- **Este directorio** — el plano técnico debajo de eso: dónde viven los secretos, qué corre como cron, qué hacer cuando se rompe, cómo accedemos.

## Estado actual del relevamiento

### Confirmado contra código (repo) y validado contra VPS reales

- ✅ Topology multi-VPS con orquestador en VPS1
- ✅ Pipeline Stripe → Airtable → cron → setup_cd_project
- ✅ Cron de provisioning corre en VPS1 (`*/5` para `process-airtable.sh`)
- ✅ DNS de tenants en VPS2 apunta correctamente a 179.43.124.219 (R9 NO se materializó en producción — el script real del VPS sí parametriza la IP, aunque el del repo no)
- ✅ 7 webhooks Slack configurados
- ✅ Acceso SSH por key configurado (`vps1-claude` y `vps2-claude` en `~/.ssh/config`)

### Sprint 2 ejecutado 2026-04-28 — resumen

| Riesgo | Acción ejecutada |
|---|---|
| **R4** | ✅ `QUEUE_CONNECTION=database` + supervisor con `bewpro-queue` worker (max-time 1h, autorestart) |
| **R7** | ✅ Comando `bewpro:healthcheck` con DNS público externo (`--external-dns=8.8.8.8` por default), scheduled cada 6h con guard `BEWPRO_HEALTHCHECK_ENABLED` |
| **R1 final** | 🟡 `sync-scripts.sh` creado, cron diario `0 7 * * *` con `--check --slack` instalado. Pendiente: push del commit `9fb73304` al GitHub para que drift = 0 |
| **R21** (nuevo) | 🟡 VPS1 es DNS authoritative para `bewpro.com` con zona local stale. Mitigado en healthcheck con `--external-dns`. Otros paths internos (exim, AutoSSL) pueden seguir usando DNS local stale — investigar. |
| **R22** (nuevo) | Drift Airtable: 13/22 Active sin Cpanel_User backfilleados (Manual con cPanel real). 10 records sin sitio (8 Stripe + Ofinita + ICG) → decisión humana. |
| Cleanup | ✅ `scripts/bewpro/` vacío. Canónicos en `infrastructure/scripts/`. Legacy en `docs/_legacy/scripts-bewpro-old/`. |

### Sprint 1 ejecutado 2026-04-28 — resumen

| # | Riesgo | Acción ejecutada |
|---|---|---|
| **R5/R18** | Versiones viejas en `/root/scripts/` | ✅ 37 archivos movidos a `/root/scripts/.archive/2026-04-28/` con README |
| **R10** | Webhooks Slack publicados en doc | ✅ Falso positivo (ya estaban truncados); doc clarificada |
| **R10b** | URLs Slack completas en `email_to_slack.php` con perm `rwxr-xr-x` (nuevo descubierto) | 🟡 Script refactorizado para leer de `/home/lacompany/scripts/.slack-webhooks.env` (perm 640); script perm 750. **Pendiente**: rotar los 6 webhooks |
| **R11** | 0/39 tenants tenían `schedule:run` en cron | ✅ 39/39 backfilleados; `setup_cd_project[2,4].sh` parcheados con step 11 |
| **R12** | `MAIL_PASSWORD` hardcoded en repo + VPS | ✅ Password rotada (`uapi passwd_pop`), repo + VPS limpios, `.airtable.env` con `SMTP_*` vars, scripts leen de env |
| **R15** | Cron `-2 8 * * *` para check-subscriptions con sintaxis inválida + script interactivo | ✅ Script con `--auto/--state/--no-restore/--dry-run`; cron `0 8 * * *` con flags |
| **R16** | DNS roto en 2 tenants olympus-group | ✅ DNS A creados en Hostinger zone, AutoSSL disparado, Let's Encrypt emitido |
| **R3** | SSH passwords expuestas + auth por password habilitado | 🟡 Key `bewpro_claude_local_ed25519` instalada en ambos VPS; `~/.ssh/config` con `vps1-claude`/`vps2-claude`. **Pendiente**: key personal de Coke + `PasswordAuthentication no` + rotar passwords |
| **R1** | Scripts orquestadores solo en VPS, repo desactualizado | 🟡 13 scripts importados a `infrastructure/scripts/{orchestrator,provisioner,billing,utility,email-pipes}/`. **Pendiente**: política de sync continuo (git pull desde VPS) |
| **R9** | `HOSTINGER_SERVER_IP` hardcoded en repo | ✅ Resuelto al sincronizar repo↔VPS (R1) |

Riesgos abiertos para Sprint 2/3: R2, R4, R6, R7, R8, R13, R14, R17, R19, R20.

### Hallazgos validados contra VPS (capturados durante Sprint 1)

- ✅ Multi-VPS topology (VPS1 orquestador, VPS2 hosting puro)
- ✅ Pipeline Stripe → Airtable → cron VPS1 → setup_cd_project*.sh
- ✅ `process-airtable.sh` real (599 líneas) parametriza correctamente `TARGET_SERVER_IP` — DNS de VPS2 tenants OK
- ✅ Cuentas: 30 (VPS1) + 9 (VPS2) = 39 tenants
- ⚠️ Smallstep SSH CA solo en VPS2 (R17 — pendiente decidir)
- ⚠️ 8 records Airtable con Cpanel_User pero `NOT FOUND` en ningún VPS (drift Airtable↔producción — anotado para review)
- ⚠️ `SLACK_WEBHOOK_URL` vive en `/root/scripts/.airtable.env` (además de `.env` Laravel)
