Files
apps-registry/workloads/docs-portal/docs/aprendizajes/notas-sueltas.md
T
devops 056a7fb76a docs(docs-portal): Fase 2 - contenido narrativo real de arquitectura/decisiones/aprendizajes
Reemplaza los placeholders "TODO (fase 2+)" por narrativa completa,
grounded en el codigo/manifiestos/incidentes reales del lab (no
generico):

- ADR 0001 (por que k3d) y ADR 0002 (por que Argo CD): pasan de
  template vacio a Contexto/Opciones/Decision/Consecuencias reales,
  apoyados en known-issues.md (blackhole MTU) y en la config real de
  ecommerce-app.yaml.
- vision-general.md: el "por que" de cada frontera de confianza del
  diagrama.
- gitops-flujo.md: ejemplo real con hashes de commit (Fase 3b de
  ADR 0006, v1.0.171 -> hotfix -> v1.0.172), selfHeal explicado con el
  syncPolicy real del repo.
- red-y-exposicion.md: diagrama de terminacion TLS real, por que todo
  va "proxied", patron de diagnostico "interno sano, publico roto".
- glosario.md: 9 terminos nuevos, cada uno con ejemplo real y
  verificado del repo (Namespace, ResourceQuota, LimitRange,
  NetworkPolicy, Deployment, Service, Ingress, StatefulSet, Init
  container).
- notas-sueltas.md: MinIO/S3, limites reales del subscriber
  revalidate-storefront.ts, que se automatizaria desde cero.

Validado con `docker build --target build` (mkdocs build --strict,
mismo paso que el pipeline real) -- cero links rotos, cero warnings.
2026-08-26 23:51:18 -05:00

84 lines
4.8 KiB
Markdown

# Notas sueltas / aprendizajes
> Esto es un scratchpad estructurado, no un playbook — sigue creciendo
> con notas cortas a medida que aparecen. Cada entrada está extraída de
> un incidente o hallazgo real ya documentado en otra parte del sitio,
> no es especulación.
## Gotchas de Medusa v2
- El Store API (`/store/products`, validado por `StoreGetProductsParams`,
`.strict()`) **no acepta** `currency_code` ni `country_code` para
resolver precios calculados — solo `region_id` explícito. Ver
[playbook de precios](../playbooks/incidente-precios-medusa.md).
- El campo `thumbnail` de un producto **no se autocompleta** a partir
del array `images` — hay que setearlo explícito desde el Admin si el
frontend lo usa como imagen hero en listados.
## MinIO / S3 provider
- Medusa sube imágenes de producto a MinIO (`minio-svc:9000`, bucket
`ari-products`) usando el provider S3-compatible estándar — MinIO no
sabe que no es AWS real, y Medusa tampoco necesita saberlo.
- La URL pública que termina viendo el navegador **no** es la interna
(`minio-svc:9000`): es `S3_FILE_URL=https://media.cruzcloud.net/ari-products`,
un dominio propio proxied por NPM hacia el mismo MinIO. Esto tiene
una consecuencia directa que ya rompió producción una vez: si
`media.cruzcloud.net` deja de rutear bien (mismo patrón de
`forward_host` roto que el resto del sitio), **todas** las imágenes
de producto del storefront se caen aunque MinIO y Medusa estén
perfectamente sanos — porque el navegador nunca habla con MinIO
directo, solo con esa URL pública. Ver [Red y exposición](../arquitectura/red-y-exposicion.md).
## Subscriber `revalidate-storefront.ts` y sus límites
- Escucha 6 eventos de Medusa (`product.created/updated/deleted` +
los 3 equivalentes de `product-variant`) y por cada uno hace un
único `POST` a `${STOREFRONT_URL}/api/revalidate` con un header
secreto (`x-revalidate-secret`) — esa ruta del frontend llama
`revalidateTag("medusa-products")` de Next.js.
- **Se degrada solo, no tira el evento entero**: si
`STOREFRONT_URL`/`REVALIDATE_SECRET` no están configurados, o el
`fetch` falla, solo loguea un `warn` y sigue — un fallo de red hacia
el frontend nunca revierte ni bloquea la operación real en Medusa
(crear/editar un producto). Mismo criterio de "degradar, no romper"
que se repite en el resto del storefront (`searchWithFacets`
opcional, `/api/search` cayendo a `{}` si Meilisearch no responde).
- **Límite real, todavía no un problema**: no hay debounce ni
deduplicación — si una operación dispara varios eventos juntos (ej.
editar un producto con 3 variantes a la vez), son varios `POST`
independientes al mismo endpoint. `revalidateTag` de Next.js es
barato e idempotente, así que hoy no se nota, pero si el catálogo
creciera mucho y las ediciones masivas se volvieran frecuentes, sería
el primer lugar donde agregar algún tipo de agrupación.
## Qué haría distinto si volviera a montar este lab desde cero
- **Fijar `TUNNEL_TRANSPORT_PROTOCOL=http2` desde el día uno** (ver
[ADR 0003](../decisiones/0003-por-que-http2-sobre-quic-tunnel.md)) y
**ajustar el MTU de `flannel.1` desde el primer `deploy-lab.sh`** —
ambos terminaron siendo incidentes reales
(504 intermitente, blackhole cross-node) que en retrospectiva eran
predecibles: red doméstica con NAT agresivo + Docker-in-Docker
multi-nodo son una combinación conocida para tener problemas de MTU
y de transporte UDP. Hoy los dos ya están automatizados
(`fix_flannel_mtu` en `deploy-lab.sh`, la variable de entorno del
túnel), pero se aprendieron reactivamente, no se anticiparon.
- **Usar `git merge-base --is-ancestor` para la promoción segura del
CI desde el primer pipeline**, no después de ver la condición de
carrera en vivo (dos pipelines corriendo en serie sobre el mismo
commit, el segundo pisando o saltándose la promoción del primero).
El patrón correcto no es complicado una vez que se conoce — el costo
fue no anticiparlo.
- **Separar siempre "chequeo de disponibilidad" de "migraciones"** en
init containers distintos, y que el chequeo use el mínimo de
parámetros posible (host/puerto/usuario/db) en vez de reusar una URI
de conexión pensada para la app. Confirmado como decisión correcta en
el [incidente de crashloop de Medusa](../playbooks/incidente-crashloop-medusa.md).
- **No escribir un script que regenere credenciales completas en cada
corrida** (`create-commerce-secrets.sh` rota JWT/COOKIE/passwords de
Postgres/Redis/MinIO enteros cada vez que se ejecuta, incluso si solo
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.