v0.118.0 — La marca, y todo lo que la QA encontró
2026-09-06🔥 Duelsmith ya tiene cara. Un yunque con dos espadas cruzadas sobre el fuego: lo verás en la pestaña del navegador, y cuando compartas un enlace del juego aparecerá con su imagen.
🖱️ El primer clic ya no se pierde. Si entrabas a la escalera o a la tienda y hacías clic enseguida, a veces no pasaba nada y había que repetir. Se arregló de raíz.
🔑 Y volver después de un rato ya no te echa. Si dejabas una pestaña abierta y volvías, te mandaba a la pantalla de iniciar sesión; ahora te quedas en el juego, y si la sesión caducó lo dice con nuestra propia página.
🧹 Además, muchas cosas pequeñas que se notan: una página de «no existe» con nuestra cara y en tu idioma · el editor de plan abre con tu campeón y deja de pedirte que inicies sesión cuando ya entraste · la tienda muestra el nombre de tu campeón en las vistas previas, no el de tu cuenta · los aspectos de objeto ya enseñan lo que son · las compras que quedaron a medias dejan de decir «el pago se está acreditando» para siempre · varios textos que seguían en inglés ahora están en español · y el banner de «ganaste tu primer combate» ya no le sale a quien lleva 157.
Registro de cambios (dev, EN)
Brand
- The mark (Rj's A4, 31 Aug draw) wired as
favicon.ico/icon.png/apple-icon.pngvia the App Router file conventions, pluspublic/brand/*derivatives and a 1200×630 default share card. /api/og/sitemarked SUPERSEDED, not deleted: it read its copy from the live landing catalog so the card could not drift from the page. The upgrade that keeps both is written at the top of it.
Launch QA sweep (docs/launch-qa-2026-09-05.md)
- Q2 —
providers.tsxreturned a different ROOT ELEMENT TYPE once PostHog's asyncloadedcallback fired, so React tore down and rebuilt the entire app once per cold load. That was the dropped first click. Second half:disabledin the SSR HTML, spinner CSS-delayed 150 ms. - Q6 · Q7 — branded, localized 404 on both public hosts; the site host's miss rewrites inside its own layout with an explicit
status: 404. Deny surfaces keep their anonymous plain 404 on purpose. - Q3 · Q4 —
/plangates its public-mode chrome on the state it already resolved, and the editor seeds from the champion instead of the hardcoded warrior default (which is exactly 4 rules — the number that disagreed with/lab). - C7 · C8 — the public case prints one heading and labels the rating; the first-win banner's predicate now carries recency (an append-only step flag never could).
- C4 · C5 — English reaching ES players, the two reported and the class behind them.
- M2 · M3 · M4 — champion name in store previews; abandoned purchases as a DERIVED display state with zero writes; skin previews (the art existed —
loading="lazy"+ an inset glow on an empty wrapper was the dark blurred square).
Auth — isAuthenticated() REDIRECTS on an expired token and the SDK's validator checks the signature only, never exp. Replaced with getUser() + an explicit expiry check that fails CLOSED. tests/setup.ts lacked getAccessTokenRaw, so the entire route suite had been exercising the fail-open branch and never the expiry check.
Hosts — dev is *.dev.duelsmith.com (Rj, 6 sep); *.develop.fibonaxis.dev retired. The sweep found four hardcoded fallbacks naming the retired host, two of them on the Stripe return URLs and on every link in every email we send.
Gates — check:no-native-select refused an exemption written the way its own header describes; the i18n key gate could not read a dotted namespace; a new purchases-abandoned copy anchor.