diff --git a/CLAUDE.md b/CLAUDE.md index 45ef697..80e56c6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1823,6 +1823,170 @@ Dos cosas que quedaron como práctica: una sesión futura lee la ficha, ve hallazgos jugosos y sale a ofrecer. La separación no es orden: es lo que evita ese error. +## 2026-08-30 — Sesión remota · Auditoría de restaurantes: el bot, la red, y tres formas de mentirse solo + +Jornada larga sobre la línea de restaurantes. **El detalle —qué locales, qué +encontró cada uno, precios y táctica— NO está acá**: vive en +`restaurantes-prospectos-y-hallazgos.md`, que se entregó por el chat y va a las +memorias locales del Mini (`~/.claude/projects/-Users-map/memory/`). Son +negocios reales, con nombre, a los que todavía no se les reportó nada, y este +repo es público. **Antes de retomar esta línea desde una sesión remota, hay que +pedirle ese archivo a Mario por el chat** — sin él se razona con la mitad del +contexto. + +Acá va solo el método, que es lo transferible. + +### 🔑 El hallazgo que más rinde: `NODE_USE_ENV_PROXY=1` + +**El `fetch` de Node ignora `HTTPS_PROXY` por defecto.** Por eso un script en +Node ve una red distinta que `curl`, y da 403 hasta para destinos que sí están +permitidos. Node 22 trae `EnvHttpProxyAgent` detrás de esa variable de entorno. +Medido, mismo contenedor, mismos destinos: + +| Destino | `node` a secas | `NODE_USE_ENV_PROXY=1` | +|---|---|---| +| dominio propio en Vercel | **403** | **200** | +| `places.googleapis.com` | alcanzable | alcanzable | +| destino bloqueado | 403 | rechazado *(correcto)* | + +Sin la flag **todo parece caído**. Con la flag quedan solo los rechazos reales. +Invocación completa: + +```bash +NODE_USE_ENV_PROXY=1 NODE_EXTRA_CA_CERTS=/root/.ccr/ca-bundle.crt node script.mjs +``` + +Costó media sesión encontrarlo y explica rojos falsos de sesiones anteriores. + +### El mapa de la red, medido con `curl` (30-ago) + +- ✅ **`places.googleapis.com` PASA.** Devolvió `403 "use API Key"` con cuerpo + JSON — **eso lo escribió la API, no el proxy**. Con una key de Places API + (New) se puede consultar la ficha de Google de cualquier negocio **desde una + sesión remota**, sin navegador y sin ser dueño de la ficha. +- ✅ Dominios propios en Vercel: 200. +- ❌ Rechazados en el CONNECT (000): `google.com`, `linkedin.com`, `sec.gov`, + `nominatim.openstreetmap.org`, `overpass-api.de`, `api.foursquare.com`, y los + sitios comerciales de terceros que se quisieran leer. +- ❌ **No hay atajo genérico**: `r.jina.ai`, `allorigins`, `serpapi` y + `api.search.brave.com` están todos bloqueados. + +**El patrón que generaliza, y es el más reusable de la sesión: una función +propia en Vercel es un primitivo de fetch legal.** Vercel tiene red abierta, la +sesión alcanza los dominios propios. Se despliega una función de 30 líneas y la +sesión le habla a su propio dominio para leer cualquier sitio. Va con token +obligatorio y guarda contra IPs privadas: **un fetcher abierto es un SSRF con tu +dominio**, y sin el secreto debe fallar cerrado (misma decisión que +`maarmapa-media`). + +### Tres formas de mentirse solo que aparecieron el mismo día + +Las tres las cazó el propio código al correrlo, no una revisión. + +1. **Un ítem no medido vale `null`, no cero.** Un cero se le muestra al cliente + como hallazgo; un chequeo que no corrió no es un hallazgo. Distinguirlos es + la diferencia entre un informe mostrable y uno peligroso. +2. **Cobertura mínima antes de dar un puntaje.** La primera corrida escupió + **"100/100"** midiendo dos ítems de cien y aprobando los dos. **Normalizar + sobre poco no produce un puntaje humilde: produce uno falsamente seguro.** + Ahora, bajo 60% de cobertura, se niega a puntuar y entrega la lista de lo que + falta mirar. +3. **Un control positivo que no recorre el mismo camino que la medición no es + un control: es otra medición.** Pasó **dos veces en el día**. Primero un + control ausente hizo que un dominio propio se informara como *caído* cuando + lo caído era la red del bot. Después, ya con control, apuntaba a un destino + directo mientras las sondas iban a ir por el proxy propio — rojo falso que + apagaba ejes enteros del informe. + +Corolario de la 3: **cuando el chequeo falla, el mensaje tiene que nombrar la +causa probable**, no decir "la red no anda". El de acá dice *"hay HTTPS_PROXY +pero el fetch de Node lo ignora: relanzá con NODE_USE_ENV_PROXY=1"*, porque esa +causa es imposible de adivinar. + +### Un cero del índice es un dato sobre tu consulta, tanto como sobre el mundo + +Tres búsquedas seguidas devolvieron cero para el nombre de un local. Se anotó +como **no concluyente** en vez de convertirlo en el hallazgo jugoso que +parecía. Estaba bien: el nombre era otro. **La regla ya escrita —el índice +como fuente secundaria, jamás para citar— vale también para sus ausencias.** + +Y su reverso, que sí es método útil: **cuando no podés abrir la página, +preguntale al índice qué sabe de ella; lo que el índice NO sabe es el +diagnóstico.** Eso sigue funcionando, pero se rotula "por confirmar" y se +verifica en pantalla antes de mostrárselo a nadie. + +### El patrón de los títulos: mirar lo que la máquina guarda como nombre + +De los locales auditados, **cinco de cinco** tenían el `