todos-contra-el-fuego-web/PENDIENTE.md
vjrj 6b6f02d92d quality: web debt batch (tests runner, FireContainer, rate-limit, maps, i18n)
Independent-of-prod quality debt from PENDIENTE.md §2:

- test: migrate broken Jest -> meteortesting:mocha. Tests rewritten to chai +
  Meteor 3 async APIs, moved to test/server/ (server-only). test/server/
  00-setup.test.js re-runs the collection2/accounts init that `meteor test`
  skips (no server/main.js). New comments method + mediaAnalyzers coverage.
  Dropped rest.test.js (removed meteor/http; covered by smoke/). 36 passing.
- fix: scope FireContainer read by the URL _id on the archive route instead of
  a selector-less FiresCollection.findOne() (imports/ui/pages/Fires/Fires.js).
- feat: rate-limit abusable publications via rateLimitSubscriptions (fireFrom*
  and comments.forReference 5/1000ms; geo subs 10/1000ms).
- perf: append loading=async to the Google Maps loader URL (Gkeys.js).
- deps: meteor-accounts-t9n 2.0 -> 2.6 (no gl build -> keep gl->es fallback,
  documented); add 3 missing gl/common.json keys (0 missing now).
- deps: drop jest/babel/enzyme, add chai.
2026-07-21 22:59:06 +02:00

6.7 KiB

Pendiente — web "Todos contra el fuego" (rama meteor3-wip)

Estado a 2026-07-18. La migración Meteor 1.6 → 3.1 + MongoDB 7 está completa y verificada (server async, React 18, web renderiza, smoke REST byte-idéntico). Lo que falta, agrupado. Ver UPGRADE.md para el detalle de lo ya hecho.


1. Modernización de librerías react-* antiguas (deuda de front grande)

Funcionan en React 18 por compatibilidad heredada, pero ensucian la consola en desarrollo (no en producción) y bloquean el salto a React 19. Estado:

Lib De → A Estado
react-helmet 5.2 → react-helmet-async 2 hecho
react-i18next + i18next 7.4/10.5 → 14/23 hecho
react-bootstrap 0.31 → 2 hecho (CSS sigue en Bootstrap 4)
reactstrap + 3 deps muertas eliminadas (0 usos)
react-router-dom 4.2 → 6.30 hecho (history 5, HOC withRouterCompat)
react-leaflet + leaflet 1.8/1.3 → 4.2/1.9 hecho (Map→MapContainer, refs directas, useMap/useMapEvents; 4 plugins reimplementados: MapControl portal, GoogleMutantLayer, fullscreen, sleep/graphicscale vanilla; ver UPGRADE.md)
Bootstrap CSS/JS 4.1 → 5 ⏸️ diferida (carrusel/navbar jQuery BS4; ver UPGRADE.md)

Lo verificado en navegador tras cada lib: /, /fires, /fire/archive/<hex>, /login, /subscriptions + consola. Smoke REST byte-idéntico en cada paso. Limpieza de warnings restantes YA hecha: defaultProps en componentes función → parámetros por defecto; UNSAFE_componentWillReceiveProps (FromNow, FireStats, Fires, SelectionMap) → getDerivedStateFromProps/componentDidUpdate; Reconnect (banner Blaze meteorStatus con findDOMNode) → React nativo con useTracker(Meteor.status); react-share 2→5 y react-progress-bar.js → progressbar.js (ambos tiraban findDOMNode/defaultProps); y react-leaflet 1.8→4.2 (mapa central, 4 plugins reimplementados). Tras esto la consola tiene 0 warnings de React en las rutas principales (verificado forzando re-render en / y /fires). Único resto para React 19: el <Blaze serverFacts> de Status.js (findDOMNode), solo en /status (admin).


2. Deuda funcional / de calidad de la web (independiente de prod)

  • Comentarios (feature React nueva): verificación manual en staging. El smoke no llega a la UI. Los métodos (insert/edit/remove/like/dislike) y el embed (mediaAnalyzers) ya están cubiertos por mocha (test/server/comments.test.js), pero quedan por probar a mano en una página de fuego:
    • publicar / editar / borrar un comentario (UI React)
    • like / dislike (toggle)
    • render del embed de imagen y de YouTube
    • email a otros comentaristas (onCommentAdd.js, entrega real de correo)
  • FireContainer endurecido (imports/ui/pages/Fires/Fires.js): el findOne() sin selector ahora se acota por el _id de la URL en la ruta archive (new Meteor.Collection.ObjectID(id)); en active/alert/hash cada publicación deja un único fire en minimongo, así que el read vacío es correcto.
  • Suite de tests con runner (meteortesting:mocha). npm test corre meteor test … --driver-package meteortesting:mocha (watch: npm run test-watch). Tests reescritos a chai + APIs async de Meteor 3 en test/server/*.test.js (server-only), incluyendo cobertura nueva de los métodos de comentarios. Jest y rest.test.js (ya cubierto por smoke/) eliminados. 36 passing. Pendiente menor: portar los casos de token inválido (401/400) de rest.test.js al smoke.
  • Rate-limit de publications (imports/startup/server/api.js): reglas type: 'subscription' vía rateLimitSubscriptions — 5/1000ms en fireFrom* y comments.forReference; 10/1000ms en las subs geo (map pan/zoom).
  • Google Maps con loading=async (imports/startup/client/Gkeys.js): se envuelve GoogleMapsLoader.createUrl para añadir el parámetro (el paquete google-maps npm no expone hook). Verificar en staging que el mapa carga y el aviso de consola desaparece.
  • meteor-accounts-t9n actualizado a ^2.6.0 (es/en OK). El paquete sigue sin build gallego (gl), así que se mantiene el fallback gl→es documentado en i18n.js. Traducción gallega de la app (gl/common.json): 0 claves faltantes.
  • Salto Bootstrap 4→5 (CSS/JS) pendiente: react-bootstrap ya está en v2 y corre sobre el CSS Bootstrap 4 actual (alexwine:bootstrap-4) con un único shim .form-label en forms.scss. El salto a Bootstrap 5 npm está diferido porque el carrusel del home (bootstrap-carousel-swipe, jQuery/BS4) y el collapse del navbar dependen del JS jQuery de BS4 (data-toggle, data-slide). Al hacerlo: importar bootstrap@5 SCSS+JS, reescribir el carrusel (BS5 trae swipe nativo → quitar el plugin), data-toggledata-bs-toggle, ml-automs-auto, revisar new-age.scss/custom.scss/bootstrap-overrides.scss.
  • Limpieza menor: migración 217 // TODO remove falsepositives lowercase collection; prerender.js gating comentado; sección per-fire del sitemap eliminada (era código muerto tras firesMapEnabled=false).

3. Observabilidad (Sentry/GlitchTip) — casi cerrado

  • Server-side reporta a GlitchTip; cliente vía túnel /sentry-tunnel (esquiva el 503 de Cloudflare). DSN en settings-development.json (gitignored).
  • Pendiente: poner el DSN en el METEOR_SETTINGS de producción y confirmar que el servidor de prod alcanza GlitchTip (IPv4). Nota: el túnel es un relay acotado al proyecto propio (aceptable, documentado).
  • Consola de dev: warnings de librería restantes solo se van con el punto 1.

4. Cutover a producción (infra — fase 3, es lo grande)

  • Migrar datos Mongo 3.2 → 7 (mongodump/restore) en el servidor real.
  • Desplegar el stack (Docker) al servidor limpio vía el ansible de Comunes — NO al viejo shiva. Ver RUNBOOK.md (stack compose local validado).
  • Coordinar orden con notificaciones: la web NO debe desplegarse antes de que el microservicio tcef-notifications emita en prod (si no, los usuarios dejan de recibir avisos). Ver dependencia en UPGRADE.md.
  • Secretos de prod (METEOR_SETTINGS, no el fichero gitignored), cron del GeoLite2 City (MaxMind) en el nuevo host, proxy/TLS por el ansible compartido.

5. Fuera del repo web (bloquean el "hecho" global, pistas aparte)

  • tcef-notifications: rollout por canal shadow→canary→full (FCM en canary superado; email y telegram pendientes) y redeploy del servicio actualizado.
  • App móvil fires_flutter: republicación en Play Store.

Regla de trabajo en todo lo anterior: commits locales atómicos en meteor3-wip, smoke REST byte-idéntico tras cada cambio, verificación visual en navegador, y NUNCA git push.