KILL LIST · POST-MORTEMS

Lo que se rompió.
Lo que costó. Lo que cambié.

Si solo cuento las cosas que funcionan, el manual sale incompleto. Aquí están los kills, los pivots, y los costos reales — con números y fechas.

«Half of life is just showing up. The other half is showing up after you got knocked down.» — la diferencia entre el operador serio y el guru de Instagram es esta página. Los receipts incluyen los costos.
ERROR #001 · COSTO REAL

Google Cloud API key hijack — $1,869

18 de abril de 2026 · MapaDeCaboRojo.com

-$1,869.68

Qué pasó

La API key de Google Cloud (Gemini, Maps, etc.) estaba en .env.local como VITE_GOOGLE_API_KEY. Lo que yo no sabía: Vite embebe TODAS las variables con prefijo VITE_ en el JavaScript público. La key terminó en el bundle compilado de mapadecaborojo.com, accesible a cualquier bot que mire el source.

Bots la encontraron y la usaron pa’ llamadas no-autorizadas al API de Gemini. $1,869.68 en cobros vs los $6.80/mes que normalmente gasto. Mastercard rechazó el cargo de $1,000 (threshold) — balance pendiente $1,369.68. Google Cloud suspendió el proyecto VeciAI automáticamente por «hijacked resources.»

Por qué falló (root cause)

La key tenía 45 APIs habilitadas con cero restricciones. Sin HTTP referrer restriction, sin IP whitelist, sin límites por API, sin budget alerts. Una sola key haciendo todo. Una sola pérdida de control = factura de $1,869.

El error mental era «esta key es solo pa’ testing local» — pero al desplegar Vite a Vercel, el bundle público heredó la variable. El framework hizo lo que dijo que iba a hacer; yo no leí la documentación.

Qué cambió permanente

  • Regla nueva en mi CLAUDE.md (gate pre-deploy): ningún server-key con prefijo VITE_, NEXT_PUBLIC_, ni REACT_APP_. Si la key cobra por uso, no puede tener prefijo público. Punto.
  • Keys separadas por uso: una pa’ frontend (Maps JS solo, restringida por HTTP referrer a *.mapadecaborojo.com/*), otra pa’ server (restringida por IP).
  • Budget alert obligatorio antes de habilitar cualquier API que cobre por uso. $25/mes alert, daily quotas por API.
  • Checklist pre-deploy: grep AIzaSy en el dist/ después de cada build. Cero matches = safe. Si aparece, la key está expuesta.

La lección de fondo

El stack ya no perdona la ignorancia documentada. Antes podías «moverte rápido y romper cosas» — hoy un bot extrae tu key del bundle en 30 segundos. Leer la documentación de tu framework no es opcional. Especialmente la parte que dice «qué se queda en el cliente.»

ERROR #002 · CONSECUENCIA

Proyecto VeciAI suspendido por Google Cloud

18 de abril de 2026 · 1 día down + recuperación

SUSPENDED

Qué pasó

Cuando Google detectó el patrón de fraude del Error #001, no me llamó. No me mandó email pa’ avisar. Suspendió el proyecto entero — VeciAI — automáticamente. Eso significaba: cero acceso a la consola, cero acceso a las keys, cero forma de cortar el sangrado yo mismo. Solo un botón de «appeal» en el dashboard.

VeciAI era el proyecto que albergaba claves para el bot *7711 (la cara pública del directorio CaboRojo.com). Si el bot dependía 100% de esas keys, el bot se hubiera caído junto con el proyecto. Por suerte el bot ya estaba mayormente sobre Supabase Edge Functions, no sobre Google Cloud.

Qué cambió permanente

  • No depender de un solo proveedor pa’ infraestructura crítica. El bot *7711 ya no toca Google Cloud — vive completo en Supabase + Twilio. Single point of failure eliminado.
  • Servicios con auto-suspension van en proyectos no-críticos. Si Google Cloud puede suspenderte sin aviso, no metas ahí lo que tu negocio principal necesita pa’ funcionar.
  • Manual review > auto-suspension cuando se elige hosting. Vercel, Supabase, Netlify — todos tienen review humano antes de cortar. Eso es preferible aunque cueste un poco más.

La lección de fondo

Operar solo significa que cuando algo se rompe, no hay equipo que te cubra. La infraestructura tiene que estar diseñada pa’ que un solo problema NO pueda apagar el negocio. Redundancia no es lujo de empresas grandes — es supervivencia básica del operador solo.

ERROR #003 · DECISIÓN

PalOeste — el directorio que sí funcionó pero no escaló

11 de mayo de 2026 · paloeste.com sunset

SUNSET

Qué pasó

PalOeste.com fue mi primer directorio del oeste de Puerto Rico. Admin interno (AdMent) + frontend público. Funcionó técnicamente. Tenía sponsors. Tenía tráfico. Pero el brand público nunca tuvo masa crítica suficiente pa’ justificar el costo de marketing dual (caborojo.com + paloeste.com en paralelo).

Por qué falló (root cause)

Dos brands hablándole a la misma audiencia geográfica con el mismo mensaje. Si el ROI de caborojo.com era 10× mejor (más sponsors, más tráfico, más reach FB), seguir empujando paloeste era diluir energía. El error fue no decidirlo 6 meses antes — esperé hasta que estuvo claro que estaba duplicando trabajo, no diversificando.

Qué cambió permanente

  • El admin AdMent sigue corriendo internamente — sirve a la operación de CaboRojo.com. Lo útil se queda.
  • Brand público de paloeste.com sunset — no se promociona, no aparece en bio, no aparece en sign-off, no entra en links cross-promo.
  • Dominio expira 2027. No se renueva. Después se decide: drop o redirect 301 a caborojo.com.

La lección de fondo

Dos brands para una audiencia es uno y medio. Lo que técnicamente funciona y comercialmente no escala no es «diversificación» — es overhead emocional. Mejor un brand fuerte que dos mediocres. El admin sigue trabajando; la fachada se cierra.

ERROR #004 · INCIDENTE

JaguarPC compromise CVE-2026-41940 — y el wave 2 que pre-cleanup missed

6 al 11 de mayo de 2026 · 4 sitios cPanel

MULTI-SITE

Qué pasó

JaguarPC reportó CVE-2026-41940 multi-site compromise el 6 de mayo. Mis 4 cuentas cPanel (caborojo, angeland, delvalle, doradoqu) afectadas. Wave 1 cleanup terminó May 8. Sitio restaurado May 9. Wave 2 cleanup el 11 reveló que el tarball original traía persistencia oculta — .user.ini con auto_prepend_file + dotfile webshells + mu-plugin zzz-cleanup-deactivator. Sitio limpio finalmente May 11 PM.

Por qué falló (root cause)

CentOS 7 EOL hace año y medio + cPanel versions atrás del LTS + 0 backup off-site + 0 Wordfence + 0 Cloudflare. El sitio tenía superficie de ataque 7/10. El parche tardó porque el VPS estaba unpatched por inertia operacional — «anda funcionando» significa nada cuando ataque te toca.

Qué cambió permanente

  • Risk score actual: 3.5/10 → target Phase 4 (14 días): 8.0/10. Plan ejecutable: Cloudflare + Wordfence + 2FA + Backblaze B2 + auto-updates + CVE Watch cron.
  • Lección integrada a CLAUDE.md global: «Keep servers patched.» Auto-update no es opcional.
  • Casa Digital SecurityHardener weekly canary nace de aquí — agent quincenal que detecta el próximo compromise en horas, no días.
  • Off-site backup ya no opcional. Backblaze B2 split bucket $5/mo cubriendo las 4 cuentas.

La lección de fondo

«Anda funcionando» no es seguridad — es suerte mientras dura. Patches no son opcionales. Backup off-site no es opcional. WAF no es opcional. El día que te toca CVE, ya es muy tarde para empezar.

ERROR #005 · PRODUCTO PARQUEADO

Veci Concierge Senior — el producto que Noelia aprobó pero el mercado no

28 de abril de 2026 · pre-lanzamiento

PARKED

Qué pasó

Veci Concierge Senior iba a ser un servicio mensual de remote patient monitoring para diabéticos puertorriqueños — usaría El Veci como interfaz SMS pa’ que personas mayores pudieran reportar glucosa sin app, sin Bluetooth, sin nada técnico. Noelia (mi esposa, Consultora de Farmacia) aprobó la idea conceptualmente. Hice research de mercado. Lo paré antes de invertir más.

Por qué falló (root cause)

Research reveló dos cosas: (1) la adherencia a RPM en seniors PR es brutalmente baja — incluso con clínicas activas detrás, la mayoría abandona en 60 días. (2) La logística de devices (glucómetros sincronizados, Bluetooth, training) es un costo fijo que mi modelo solo+AI no soporta sin team de soporte humano. Market gate failed antes del primer pago.

Qué cambió permanente

  • El producto NO se mata — se parquea. Si llegamos a 5+ Vitrinas pagando en CaboRojo (Goal #1 público) y el mercado RPM seniors PR muestra signal change, se revisita.
  • Veci Concierge se reorienta a Diáspora ($19-99/mo) en vez de Senior — audiencia más capaz de pagar, con device infraestructura ya en mano, menor friction.
  • Filtro pre-build nuevo: antes de cualquier producto que requiera devices físicos o hardware, validar adherencia rate del segmento target con research, no con entusiasmo.

La lección de fondo

Que alguien que confíe en ti diga «sí, hazlo» no es señal de mercado. Es señal de afecto. El mercado vota con su tiempo y su tarjeta, no con su entusiasmo prestado. Cuando research muestra que no van a usar lo que pagas, la decisión correcta es parquear — no perseguir.

ERROR #006 · ESTRATEGIA REVERTIDA

RadarDePueblo + ElMapaDePuertoRico — la replicación PR-wide que pausé

Mayo de 2026 · escalamiento prematuro

DORMANT

Qué pasó

RadarDePueblo, RadarPR, y ElMapaDePuertoRico eran mi apuesta pa’ replicar el modelo caborojo.com / mapadecaborojo.com a los otros 77 municipios de Puerto Rico. Tenía dominios. Tenía deploys. Tenía la tesis civic-tech replicable. Los paré sin sponsors pagando en CaboRojo aún.

Por qué falló (root cause)

Pretendí escalar antes de probar. CaboRojo.com tenía 2 Vitrinas pagando — no 50. Mapa tenía 1,134 places verified pero monetización inmadura. Replicar el modelo PR-wide con esa data era construir un sistema sobre arena. Le dije a Claude un domingo: «Puerto Rico, eso no me interesa por ahora.» Salió de la boca solo. Cuando me oí decirlo me di cuenta que la replicación era ego, no demanda probada.

Qué cambió permanente

  • Regla nueva: la replicación PR-wide se reactiva solo si CaboRojo llega a 5+ Vitrinas pagando + verification freshness Mapa ≥80% sostenido 3 meses.
  • Hasta entonces: RadarDePueblo + RadarPR + ElMapaDePuertoRico están DORMANT. Dominios siguen, código en repo, cero inversión activa.
  • Filtro KEEP/KILL/SUNSET aplicado: 0 revenue · 0 audience equity · scope expansion sin tracción primera = postergar, no construir.

La lección de fondo

El moat se prueba en un pueblo. Después se replica. Si no se prueba primero, escalar es construir más superficie pa’ fallar al mismo tiempo. Hiperlocal > regional, hasta que hiperlocal pague.

ERROR #007 · DOMINIO MUERTO

DescubreCaboRojo.com — tres páginas, cero claridad

Mayo de 2026 · sin tráfico

KILLED

Qué pasó

DescubreCaboRojo.com fue un «tal vez sirve» que registré por si en algún momento quería un sitio turístico independiente del directorio principal. Nunca lo construí más allá de 3 páginas estáticas. Compitió mentalmente con caborojo.com (community editorial) y con mapadecaborojo.com (verified directory) por la misma audiencia turística.

Por qué falló (root cause)

Tres dominios pa’ la misma audiencia es uno y dos tercios. Tenía caborojo.com + mapadecaborojo.com + DescubreCaboRojo. Nunca hubo respuesta clara a «¿qué hace DescubreCaboRojo que los otros dos no?» Compré optionality sin ejecutarla — la peor forma de pretender estrategia.

Qué cambió permanente

  • Aplicado filtro KEEP/KILL/SUNSET (Mapa-de-Activos canon): 0 revenue · 0 strategic IP · 0 audience equity · 0 low maintenance acumulado = KILL.
  • Dominio se dropea cuando expire. Cero tiempo más en esta superficie.
  • Regla pre-registro de dominios nuevos: si no sabes para qué es en 30 segundos, no lo compres. Optionality que no se ejecuta es deuda mental.

La lección de fondo

«Tal vez sirve» no es estrategia — es ruido futuro disfrazado de optionality. Si no sabes para qué es en 30 segundos, no es. Optionality que no se ejecuta es deuda mental.

Próximos errores se publican aquí

No tengo nada que esconder. Cuando algo más se rompa — y se romperá — entra a esta lista con las mismas 4 secciones: qué pasó, root cause, qué cambió, lección de fondo.

Subscríbete al newsletter pa’ verlos en el momento, no meses después.

Ir al newsletter →

¿Quieres ver los receipts del lado positivo? Las metas y los números están en /metas. Esta página es solo la otra mitad del cuadro completo.

El No Sin Culpa

35 scripts listos para decir NO — sin culpa, sin drama, sin explicar de más.

Descarga los 35 Scripts → Gratis