`@vite-pwa/sveltekit` pulled in `serialize-javascript@6.0.2` via
workbox-build → @rollup/plugin-terser, which is flagged for High RCE
(GHSA-5c6j-r48x-rmvq) and Medium DoS (GHSA-qj8w-gfj5-8c6v). Both fix
to >=7.0.5.
Also opportunistically bump `cookie` past 0.7.0 (Low GHSA-pxg6-pf52-xh8x)
via @sveltejs/kit — was the last-remaining Dependabot Low.
Build-time tooling only — neither package ships to the browser. Pinned
via npm `overrides` rather than `audit fix --force` because the latter
would downgrade @vite-pwa/sveltekit to 0.0.1 (breaking).
npm audit: 0 vulnerabilities. Tests 115/115. Build clean.
Phase 1 — Vietnamese-safe font + master empty state:
- Add @fontsource/roboto-condensed (700 weight, all subsets including
Vietnamese). font-display:swap. tan-tan-num now resolves the bundled
face on Android instead of system Arial Narrow.
- New MasterEmptyState.svelte: ghost 11×9 grid + "Chế độ Quản trò"
pill + readiness microcopy. Replaces the bare line of text in
MasterPanel's no-game state.
Phase 2 — Mode picker icons, color picker layout, header polish:
- Inline SVG glyphs above each mode button (player card / megaphone /
two stacked cards). Communicates role at a glance.
- Color picker wrapped in a single bordered card with "Tuỳ chỉnh"
and "Mẫu sẵn" sub-headers.
- "Mặc định" → "Đặt lại" with a bordered chip style — clearer
affordance than the previous near-invisible footer link.
- Header subline: drop tracking-[0.28em] all-caps SaaS look; replace
with dash-flanked lantern band ("— 🏮 Hội chợ TN1 —") for
fairground mood.
Phase 3 — Installable PWA + offline audio:
- @vite-pwa/sveltekit with autoUpdate. Precache app shell (~353 KB
→ 213 entries) PLUS the default voice's 92 clips so first-install
is fully offline-capable. Alternate voices fall through to a
CacheFirst runtime rule (cached on first play, 30-day TTL,
maxEntries: 400 for future-proofing).
- New static/manifest.webmanifest (Lô tô — Hội chợ TN1, theme #1565c0,
background #0a0f1f, standalone, vi).
- Icons: 192/512 standard + 512 maskable, generated from a single
rose-amber-gradient SVG source.
- app.html: manifest link, dual theme-color meta (light + dark),
apple-touch-icon, apple-mobile-web-app-capable for proper
standalone launch on iOS Safari.
- _headers: add manifest-src + worker-src to CSP; no-cache on /sw.js
and /manifest.webmanifest so deploys propagate.
Tests: 115/115 pass. Build clean (305 precache entries, 0 glob
warnings).
Reviewer concerns (addressed):
- maxEntries bumped 200 → 400 (was barely enough for 2 voices).
- Default voice precached so offline-first promise holds without
requiring users to play every clip online first.
- "do NOT add skipWaiting" comment added next to autoUpdate.
Adds vitest + happy-dom as devDependencies and npm scripts test
(one-shot) and test:watch. No SvelteKit/vite reconfig needed —
vitest auto-picks up the existing vite plugin chain.
game-logic.test.js (26 tests): generateGrid shape invariants
(9x9, exact 5/row, exact 5/col, no duplicates) over 200 random
trials; per-column number ranges (col 0 = 1-9, col 8 = 80-90);
ascending-within-column rule; isRowComplete/getWaitingNumber edge
cases; full save/load roundtrip for the persistence layer
including corrupt-JSON and wrong-shape rejection.
settings-store.test.js (12 tests): defaults frozen, load with
valid/invalid/corrupt payloads, hex regex rejects shorthand,
save persists to localStorage and pushes CSS var, reset returns
to brown default. Uses happy-dom env for localStorage and
documentElement.
code-standards.md: documents the rune globals declaration and the
.svelte.js convention for rune-using non-component modules.
Cloudflare Pages build failed with:
Error: Cannot find module '../lightningcss.linux-x64-gnu.node'
Tailwind 4 → @tailwindcss/vite → lightningcss has per-platform native
binaries shipped as optional npm packages. The lockfile generated on
this dev box (linux-arm64) only carried the arm64 binaries, so CF on
linux-x64 was missing the matching platform-specific package.
Adding lightningcss-linux-x64-gnu to optionalDependencies pins it into
the lockfile. On non-x64-linux machines npm skips it silently due to
the platform mismatch; CF Pages on linux-x64 will install it.
Pinned to 1.32.0 to match the parent dep already resolved.
Replace vanilla HTML/JS/CSS with Next.js App Router, TypeScript,
and Tailwind CSS. Responsive design with dark mode support.
All original game logic preserved: grid generation, click-to-cross,
localStorage persistence.