Aplicación de ítems REPLICAR del benchmark KF, P0 de la home y fix crítico de CSP que rompía las imágenes en producción
Continuación directa del informe AUD-20260930-003 (archivo 44 · veredicto
REPLICAR 9 · SUPERAR 6 · OMITIR 7). Este documento certifica la
implementación, verificación y despliegue en producción de los ítems REPLICAR priorizados
(R1, R3, R7, R8, R9) en las tres demos del portafolio + el P0 de la home de revendedores, junto con la
corrección de un bug de CSP que dejaba las miniaturas S3 rotas en vivo.
Todo verificado con suite PHP, requests HTTP y navegador real (Playwright) contra
streamingapps.online.
img-src)1 · Fix crítico: CSP bloqueaba las imágenes S3 en producción
goplay-mypantalla.s3.amazonaws.com) aparecían rotas en
cuentas-streaming.php en vivo. Causa: el dominio S3 no estaba listado en
img-src de la política CSP, servida por doble cabecera que se interseca:
PHP (env.php:103) + Apache (.htaccess:22, Header always set).
| Paso | Acción | Resultado |
|---|---|---|
| 1 | Agregar https://goplay-mypantalla.s3.amazonaws.com a img-src en ambas cabeceras (env.php y .htaccess) | HECHO |
| 2 | Verificación sandbox: 2 cabeceras CSP con el dominio; imágenes 200 | OK |
| 3 | Verificación producción (headers): política servida contiene el dominio S3 | OK |
| 4 | Navegador real en vivo: 13/13 imgs cargadas, de ellas 12/12 del S3, 0 errores de consola | OK |
En producción llega 1 sola cabecera CSP: header() de PHP reemplaza la entrada de igual nombre,
por lo que prevalece la política de env.php — que sí incluye el S3. La copia en .htaccess
queda como respaldo para archivos estáticos. Ambas mantienen el mismo img-src por diseño.
2 · Cambios por archivo (commit 74dbfac)
| Archivo | Ítems | Detalle | Diff |
|---|---|---|---|
| index.php | P0 | Barra de campaña (?t=ALD), $heroStats con métricas reales en .stat-strip (4 ítems: demos/clientes/revendedores/24-7), botón flotante .wa-float, .price-alt y scroll-spy en el FAQ |
+187/−26 |
| cuentas-streaming.php | R1·R3·R7·R9 | Stats (12/2/24-7), steps ghost 01–04, ancla «Desde» + pill ● Disponible, grid 2-col ≤620 px, fallbacks de imagen | +88/−5 |
| productos-dropi.php | R1·R3·R7·R9 | Stats (12/8/24-7), steps ghost 01–04, «Desde» + «Precio sugerido +20%», chips con conteos, grid 2-col móvil | +72/−4 |
| amrstore.php | R3·R7·R8·R9 | Buscador (input + botón rojo «Buscar» + JS runSearch integrado con filtros), «Desde», pill ● Disponible, steps ghost 01–03, grid 2-col ≤980/≤640, icono de caja como fallback de cards sin imagen, .product-tag oculto ≤390 px (evitaba solape con «Disponible») |
+138/−4 |
| env.php + .htaccess | CSP | Dominio S3 agregado a img-src en las dos cabeceras (deben mantenerse sincronizadas) |
+2/−2 |
3 · Mapeo ítems del benchmark (informe 44) → implementación
| Ítem | Qué copiaba de KF | Dónde quedó | Estado |
|---|---|---|---|
| R1 | Stats numéricas en el primer pliegue | Home (stat-strip), cuentas, productos, amrstore | ✓ |
| R3 | «Desde» como ancla de precio + estado de disponibilidad | Las 4 páginas (dot ● Disponible + pill) | ✓ |
| R7 | Pasos «cómo funciona» con numeración ghost | cuentas y productos 01–04 · amrstore 01–03 | ✓ |
| R8 | Buscador visible sobre el catálogo | amrstore (input + botón rojo); cuentas/productos ya tenían buscador propio | ✓ |
| R9 | Grid de 2 cards por fila en móvil | amrstore ≤980/≤640 · cuentas ≤620 · productos móvil | ✓ |
| R2 | Chips de filtro | Ya existían en las demos (no requería cambio) | YA ESTABA |
| R4·R5·R6 | Volumen B2B, stepper vs mascota, nav con emojis | No aplicables a estas páginas (decisión de scope del benchmark) | OMITIR |
.stats{1fr} de amrstore ≤640 px ·
label de datos «STREAMING · STREAMING» (duplicado viene del dato, no del estilo).
4 · Hallazgo: mezcla de trabajo con la rama del carrito
La rama paralela feat/carrito-checkout (commit 396c93e) capturó en amrstore.php
el trabajo KF anterior sin commitear junto con el código del carrito. Al restaurar el stash sobre dev
quedó un archivo incompleto (CSS sin markup, JS sin HTML).
- Clasificación hunk por hunk de
dev → 396c93e: 13 hunks → 7 míos (KF) vs 6 del carrito. - Reconstrucción: base =
stash@{0}:amrstore.php(trabajo KF completo) menos las piezas del carrito (CSS.add-cart-btn, headernavCartBtn/cartBadge, markup condicional if/else, JS Cart). - Verificación: 0 referencias a
add-cart-btn|carrito.php|amrAddToCart|amrCart_v1|cartBadge,php -lOK, 0 conflict markers. - En vivo:
add-cart-btn=0, navCart=false— la rama del carrito no se filtró a dev/prod y podrá mezclarse después con diff limpio.
5 · Matriz de verificación (evidencia)
| Check | Método | Resultado |
|---|---|---|
| Sintaxis PHP | php -l × 6 archivos | NO ERRORS |
| Suite de pruebas | php tests/run_all_tests.php en host | 26/26 · 100% (JSON restaurado post-corrida) |
| Endpoints | curl sobre /, /?t=ALD, cuentas, productos, amrstore | 5/5 HTTP 200 |
| CSP servida | curl -I en cuentas-streaming | img-src con S3 presente |
| Imágenes en vivo | Playwright → naturalWidth | 13/13 ok · 12/12 S3 |
| Buscador amrstore | Playwright → escribir «netflix» + click Buscar | 12 cards visibles (filtra) |
| Estructura amrstore | Playwright → DOM | search ✓ · 3 steps · 105 avail · 0 cart |
| Estructura home | Playwright → DOM en /?t=ALD | 4 stat-strip · campaign ✓ · wa-float ✓ |
| Consola | Playwright → console.error | 0 errores |
| Visual | 9 capturas 1440/390 px revisadas (banner PAGE=FILE como fuente de verdad) | SIN REGRESIONES |
6 · Deploy seguro a Hostinger (rsync con protectores)
Dry-run previo con --delete reveló archivos exclusivos de producción en riesgo; se añadieron excludes anclados
con / y se re-validó hasta 0 borrados antes de transferir.
| Archivo protegido | Riesgo si se borraba/sobrescribía |
|---|---|
| /database.sqlite | CRÍTICO: prod más nuevo (Sep 24) que el local (Sep 1) — enviarlo habría revertido datos CRM live |
| /goplay_database.sqlite | Base exclusiva de prod (solo existía en el servidor) |
| /whatsapp-crm/config.php | Credenciales de producción (no versionadas) |
| /producto.php · /index.html · /amrstore/ | Páginas/rutas legacy con posible tráfico o enlaces SEO |
| /whatsapp-crm/public/*.php · /whatsapp-crm/audit_licenses.php | Scripts runtime creados directamente en prod |
| /error_log · /.old.-install.php · /14-amrstore-*.html | Legacy — pendiente de aprobación para limpieza (no se borraron) |
config.json verificado byte-a-byte idéntico local↔prod antes de transferirlo (diferencia solo de mtime).
7 · Registro de entrega (Git)
git checkout tests/test_run_results.json)8 · Bitácora de la sesión
- ~19:10 — Resolución del conflicto de stash sobre
dev; diagnóstico de mezcla carrito+KF enamrstore.php. - ~19:25 — Reconstrucción por clasificación de 13 hunks; eliminación quirúrgica de 6 bloques del carrito;
php -l+ greps de verificación. - ~19:35 — Suite 26/26 en host → commit
74dbfac→ push refspec a GitHub y GitLab (dev/staging/main). - ~19:45 — Dry-run rsync: hallazgo de
database.sqlitede prod más nuevo y archivos legacy; excludes protectores; 0 borrados; transfer real. - ~19:50 — Smoke en vivo: 5/5 HTTP 200, CSP con S3, Playwright (imgs 12/12 S3, buscador, stats, 0 errores consola).
- ~19:56 — Revisión visual de 9 capturas desktop/móvil contra producción: sin regresiones.
- 20:00 — Publicación de este informe en
auditorias/46-informe-aplicacion-replicar-p0-csp-fix.html+ fila y contador enauditorias/index.html.