docs: ADR 0011 (ambiente de Staging) + notas de la sesión 2026-09-13/14
Documenta el ambiente de Staging (staging.cruzcloud.net, promoción manual, footer con version real), y agrega a notas-sueltas la correccion de bodega Cali, redes sociales reales, rediseño de galeria estilo Amazon, la leccion de min-w-0 en CSS Grid, y la remocion definitiva de la barra flotante de carrito en mobile. De paso, suma a la nav el ADR 0010 que existía en el repo pero nunca se había enlazado. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
This commit is contained in:
1 parent
009d5c63df
commit
fe4ed8005a
3 files changed
+184
-1
No files matched your search
@@ -81,4 +81,70 @@
|
||||
hacía falta agregar una clave nueva) — un script de setup inicial y
|
||||
uno de "agregar una clave a un secret ya vivo" deberían haber sido
|
||||
dos herramientas distintas desde el principio, no una sola que hay
|
||||
que saber cuándo NO correr completa.
|
||||
que saber cuándo NO correr completa.
|
||||
|
||||
## CSS Grid: un scroller horizontal sin `min-w-0` puede desbordar todo el grid
|
||||
|
||||
Encontrado en producción (2026-09-13/14) en la página de producto del
|
||||
storefront: un síntoma que parecía un bug de imágenes ("se ve como si
|
||||
abriera en tamaño real" en Chrome/Edge Android) resultó ser, en
|
||||
realidad, un desborde de layout. El carrusel horizontal de "También te
|
||||
puede gustar" (`overflow-x-auto`, sin `flex-wrap`) vivía como hijo
|
||||
directo de un CSS Grid. Por spec, el tamaño mínimo automático de un
|
||||
item de grid es el tamaño mínimo de su contenido **a menos que el
|
||||
propio item** tenga `overflow` distinto de `visible` — y como el `div`
|
||||
que envolvía al carrusel no lo tenía, el ancho mínimo intrínseco de
|
||||
*todas* las tarjetas del carrusel sin wrappear se contaba como el
|
||||
mínimo de esa columna, forzando **todo el grid compartido** (imagen,
|
||||
título, specs) a ~800px de ancho en un viewport real de ~380px.
|
||||
|
||||
**Lección reusable:** cualquier fila con scroll horizontal (carrusel,
|
||||
tira de miniaturas, chips de filtro) que sea hijo directo de un CSS
|
||||
Grid necesita `min-w-0` en su wrapper (o `overflow` seteado
|
||||
directamente en el item de grid) — si no, su contenido sin wrappear
|
||||
puede reventar el ancho de todo el grid en silencio, y el síntoma
|
||||
visible no tiene nada que ver con imágenes ni con DPR. Diagnosticado
|
||||
en vivo comparando `window.innerWidth` (reportaba el ancho
|
||||
desbordado) contra el viewport real del dispositivo.
|
||||
|
||||
## Rediseño de página de producto y correcciones de datos reales (2026-09-13/14)
|
||||
|
||||
Sesión de correcciones guiadas por capturas reales del usuario en
|
||||
navegadores reales (no reportes abstractos):
|
||||
|
||||
- **Bodega mal configurada:** `ENVIOCLICK_ORIGIN_DANE_CODE` apuntaba a
|
||||
Bogotá (`11001000`) cuando la bodega real está en Santiago de Cali,
|
||||
Valle del Cauca (`76001000`) — afectaba el cálculo real de envío
|
||||
(EnvíoClick) en cada checkout. Corregido en el ConfigMap del
|
||||
frontend, en `commerce-backend/medusa-config.ts` (incluyendo un
|
||||
fallback obsoleto que también apuntaba a Bogotá) y en el registro
|
||||
real de la bodega en Medusa (vía admin temporal, mismo patrón que el
|
||||
resto del lab para ediciones puntuales en vivo).
|
||||
- **Redes sociales y páginas de ayuda reales:** el footer enlazaba
|
||||
cuentas placeholder; se verificó en vivo la cuenta real de Instagram
|
||||
antes de linkearla (la primera sugerida no era la correcta) y se
|
||||
activaron los enlaces reales de Instagram/Facebook/WhatsApp, además
|
||||
de las páginas `/cambios` y `/preguntas-frecuentes` con contenido
|
||||
real (ya existían en código, no estaban enlazadas).
|
||||
- **Zoom estilo Amazon en la galería de producto:** iteración en tres
|
||||
pasos hasta llegar a lo pedido — `transform: scale()` sobre una
|
||||
imagen ya recortada por `object-cover` (no funcionaba: lo recortado
|
||||
nunca estaba en el DOM), superposición in-place (técnicamente
|
||||
correcta pero no la UX pedida), y finalmente una lupa que sigue el
|
||||
cursor más un panel lateral que magnifica esa región — el patrón
|
||||
real de Amazon. El tamaño/posición del panel se calcula en JS contra
|
||||
`window.innerWidth/innerHeight` en cada `mousemove` (no un
|
||||
breakpoint CSS fijo), con fallback a la superposición in-place si no
|
||||
hay espacio.
|
||||
- **Barra flotante de "Añadir al carrito" en mobile: removida, no
|
||||
reajustada.** Pasó por varias iteraciones de lógica de
|
||||
mostrar/ocultar (con `IntersectionObserver`) que seguían
|
||||
superponiéndose a otro contenido en capturas reales del usuario. En
|
||||
vez de seguir ajustando el umbral, se eliminó el componente por
|
||||
completo y se dejó el botón inline normal, visible también en
|
||||
mobile — el mismo patrón que usa la mayoría de tiendas. Verificado
|
||||
con Playwright: cero elementos `position: fixed` en la página de
|
||||
producto.
|
||||
- **Ambiente de Staging + versión real en el footer:** ver
|
||||
[ADR 0011](../decisiones/0011-ambiente-staging.md) para el detalle
|
||||
completo.
|
||||
@@ -0,0 +1,115 @@
|
||||
# ADR 0011 — Ambiente de Staging para el storefront
|
||||
|
||||
**Estado:** aceptada — desplegado y verificado en vivo
|
||||
**Fecha:** 2026-09-14
|
||||
|
||||
## Contexto
|
||||
|
||||
Hasta este punto, todo cambio de frontend se probaba directamente
|
||||
contra `shop.cruzcloud.net` (producción): el mismo push a `main` que
|
||||
disparaba el build de imagen también actualizaba el manifiesto real
|
||||
que sirve tráfico. Cada iteración de UI (rediseño de la página de
|
||||
producto, zoom estilo Amazon, ajustes mobile) implicaba validar en
|
||||
vivo sobre el sitio real, sin una red de contención — un cambio roto
|
||||
llegaba directo al usuario final antes de poder revertirlo.
|
||||
|
||||
El usuario pidió explícitamente un ambiente de Staging para dejar de
|
||||
probar en producción ("Me interesa crear el ambiente Staging para no
|
||||
estar probando en Prod").
|
||||
|
||||
## Opciones consideradas
|
||||
|
||||
| Opción | A favor | En contra |
|
||||
|---|---|---|
|
||||
| **Namespace + Ingress propios, backend compartido con Prod** — elegida | Cero costo adicional de Postgres/Medusa/Meilisearch en un NAS ya ajustado de recursos; rápido de armar reusando el mismo patrón workload+governance de `ecommerce` | Staging y Prod comparten datos reales (catálogo, inventario, órdenes) — no aísla pruebas que muten datos de negocio |
|
||||
| Backend propio para Staging (Postgres/Medusa/Meilisearch duplicados) | Aislamiento completo, se podrían probar migraciones de datos sin riesgo | Duplica el consumo de recursos de la NAS sin necesidad todavía (decisión explícita del usuario de descartar esto por ahora) |
|
||||
| Feature flags / preview deploys por PR en vez de un ambiente fijo | Sin infraestructura nueva que mantener | Gitea Actions en este lab no tiene un mecanismo de preview-per-branch ya armado; más esfuerzo de tooling que un namespace nuevo |
|
||||
|
||||
## Decisión
|
||||
|
||||
Namespace `ecommerce-staging` nuevo, con su propio Ingress
|
||||
(`staging.cruzcloud.net`) y su propio Deployment de frontend (misma
|
||||
imagen Docker que Prod), pero apuntando al **mismo backend Medusa** que
|
||||
producción (`medusa-svc.ecommerce.svc.cluster.local:9000` — FQDN
|
||||
cross-namespace, un nombre corto solo resuelve dentro del mismo
|
||||
namespace). Flujo de promoción: **todo push a `main` despliega a
|
||||
Staging automáticamente**; promover a Producción es una acción manual
|
||||
separada (`scripts/promote-to-production.sh`).
|
||||
|
||||
## Qué se armó
|
||||
|
||||
- `apps-registry/workloads/ecommerce-staging/` — overlay Kustomize:
|
||||
1 réplica (no 2 como Prod — ambiente de verificación, no de tráfico
|
||||
real), requests/limits más chicos, mismo `securityContext` que Prod
|
||||
(mismas restricciones del Dockerfile: `runAsUser` numérico,
|
||||
`NET_BIND_SERVICE`, `readOnlyRootFilesystem`).
|
||||
- `apps-registry/apps/ecommerce-staging-app.yaml` +
|
||||
`ecommerce-staging-governance-app.yaml` — Applications de Argo CD
|
||||
(workload + governance separadas, misma convención que el resto del
|
||||
lab).
|
||||
- `platform-infra/ecommerce-staging-governance/` — ResourceQuota,
|
||||
LimitRange y NetworkPolicy propios del namespace nuevo.
|
||||
- `.gitea/workflows/build.yaml` — el paso de CD (`Actualizar
|
||||
Manifiesto GitOps`) ahora apunta a
|
||||
`workloads/ecommerce-staging/frontend/patches/deployment.yaml` en
|
||||
vez del manifiesto de Prod: cada push a `main` bumpea el tag de
|
||||
imagen (y, desde el mismo día, la variable `APP_VERSION` — ver nota
|
||||
de implementación) de Staging automáticamente.
|
||||
- `scripts/promote-to-production.sh` — lee el tag actualmente
|
||||
desplegado en Staging, pide confirmación explícita, y lo aplica al
|
||||
manifiesto real de Producción (`workloads/ecommerce/frontend/patches/deployment.yaml`).
|
||||
Nunca corre automáticamente: es la única vía para que un cambio
|
||||
llegue a `shop.cruzcloud.net`.
|
||||
- Secrets `commerce-storefront` y `gitea-registry-secret` copiados
|
||||
(no regenerados) desde el namespace `ecommerce` hacia
|
||||
`ecommerce-staging`, para que el frontend de Staging tenga las
|
||||
mismas credenciales reales contra el backend compartido.
|
||||
|
||||
## Descubrimiento de red real (no solo Kubernetes)
|
||||
|
||||
Confirmado en vivo el mismo día: aunque Cloudflare tiene un wildcard
|
||||
`*.cruzcloud.net`, eso **no alcanza** para exponer un Ingress nuevo. La
|
||||
cadena real es Cloudflare → túnel `cloudflared` → **Nginx Proxy
|
||||
Manager** → `k3d-lab-cluster-serverlb` (puerto 90) → Traefik → Service.
|
||||
Cada subdominio que ya funciona (`shop`, `commerce`, `media`, etc.)
|
||||
tiene su propia fila de Proxy Host en NPM apuntando a
|
||||
`192.168.68.61:90`. Un Ingress nuevo sin esa fila devuelve la página
|
||||
por defecto de NPM aunque Traefik ya esté enrutando bien internamente
|
||||
— verificado con `curl -H "Host: staging.cruzcloud.net"
|
||||
http://192.168.68.61:90/` (funcionaba) contra el dominio público
|
||||
(seguía devolviendo la página por defecto hasta que se agregó la fila
|
||||
en NPM). Ver [Red y exposición](../arquitectura/red-y-exposicion.md).
|
||||
Esta fila de NPM la agregó el usuario manualmente — no hay credenciales
|
||||
de ese panel disponibles para automatizarlo.
|
||||
|
||||
## Nota de implementación (2026-09-14): versión real visible en el footer
|
||||
|
||||
El footer mostraba un string fijo (`v4.1`), inútil para distinguir a
|
||||
simple vista si Staging y Producción están en la misma versión.
|
||||
Se agregó una variable de entorno `APP_VERSION` (leída en
|
||||
`footer.tsx` vía `process.env.APP_VERSION`, sin necesidad de prefijo
|
||||
`NEXT_PUBLIC_` por ser un Server Component) a ambos manifiestos de
|
||||
Deployment; el mismo paso del CD que bumpea el tag de imagen ahora
|
||||
también bumpea `APP_VERSION` (vía `perl -0777` para una sustitución
|
||||
multilínea, ya que el nombre y el valor de la variable viven en líneas
|
||||
distintas del YAML — un `sed` de una sola línea no alcanza).
|
||||
`promote-to-production.sh` hace el mismo bump al promover. Verificado
|
||||
en vivo con Playwright: tras el primer push, Staging mostró `v1.0.263`
|
||||
mientras Producción seguía en `v4.1` (la imagen vieja no leía la
|
||||
variable); tras promover, ambos ambientes quedaron visualmente
|
||||
distinguibles por versión real en su footer.
|
||||
|
||||
## Consecuencias
|
||||
|
||||
- Ganado: ningún cambio de frontend vuelve a validarse por primera vez
|
||||
contra tráfico real; Staging y Producción ahora se distinguen a
|
||||
simple vista por la versión mostrada en el footer.
|
||||
- Deuda aceptada: Staging comparte datos reales de negocio con
|
||||
Producción (mismo Medusa/Postgres) — una prueba que cree o modifique
|
||||
órdenes/inventario en Staging afecta datos reales. Si esto se vuelve
|
||||
un problema, la opción descartada de backend propio para Staging
|
||||
queda como camino de escalamiento.
|
||||
- Para revertir: apuntar de nuevo `MANIFEST_FILE`/`KUSTOMIZE_DIR` en
|
||||
`build.yaml` hacia `workloads/ecommerce/...` y eliminar el namespace
|
||||
`ecommerce-staging` — el namespace de Producción no cambia de forma
|
||||
en ningún momento de este ADR.
|
||||
Reference in new issue
Block a user