feat(export): server-rendered artifacts behind one signed download URL #160

Merged
developer merged 7 commits from feature/export-server-render into development 2026-07-02 21:58:07 +00:00
2 changed files with 8 additions and 7 deletions
Showing only changes of commit fca8fd038b - Show all commits
+2 -1
View File
@@ -128,7 +128,7 @@ platform/telegram/ # Telegram side-service: cmd/validator (HMAC, no VP
renderer/ # image-render sidecar (Node + skia-canvas): runs ui/src/lib/gameimage.ts server-side for the finished-game PNG export
loadtest/ # module scrabble/loadtest: the load/stress harness
docs/ .gitea/workflows/ CLAUDE.md README.md
backend/Dockerfile gateway/Dockerfile platform/telegram/Dockerfile loadtest/Dockerfile # multi-stage distroless; gateway/Dockerfile has the `landing` target, platform/telegram/Dockerfile has `validator`+`bot` targets
backend/Dockerfile gateway/Dockerfile platform/telegram/Dockerfile loadtest/Dockerfile renderer/Dockerfile # multi-stage distroless (renderer: node:22-slim + skia-canvas + fonts); gateway/Dockerfile has the `landing` target, platform/telegram/Dockerfile has `validator`+`bot` targets
deploy/ # docker-compose (+ prod overlay + bot host) + ansible provisioning + caddy + landing + otelcol (OTLP + docker_stats) + prometheus/tempo/grafana + node_exporter + postgres_exporter; prod-deploy.sh
```
@@ -144,6 +144,7 @@ go run ./backend/cmd/backend # /healthz, /readyz on :8080
cd ui && pnpm install && pnpm check && pnpm test:unit && pnpm build # the UI
pnpm start # UI mock mode: lobby -> game, no backend
cd renderer && pnpm install && pnpm test # image-render sidecar (bundles ui/src/lib/gameimage.ts, skia smoke)
docker build --build-arg DICT_VERSION=v1.3.0 -f backend/Dockerfile -t scrabble-backend . # DICT_VERSION required (no default); gateway embeds the SPA
docker build -f gateway/Dockerfile --target gateway -t scrabble-gateway .
+6 -6
View File
@@ -813,12 +813,12 @@ authenticated caller on a finished game. The PNG is rasterized on demand by the
**`renderer` sidecar** (internal-only Node + skia-canvas running the same
`ui/src/lib/gameimage.ts` the web project unit-tests — one renderer, no drift;
`renderer/README.md`); the backend rebuilds the render payload from the journal +
`engine.AlphabetTable`, and the client's date locale plus its UI-localized non-play
labels ride the signed URL so the server render matches the player's presentation.
Nothing is stored: the artifact is re-derived from the immutable finished journal on
each GET. The only remaining platform branch is a legacy Telegram client predating
`downloadFile`, where the GCG falls back to the old clipboard copy and the image option
is not offered.
`engine.AlphabetTable`, and the client's date locale, IANA time zone and UI-localized
non-play labels ride the signed URL so the server render matches the player's
presentation. Nothing is stored: the artifact is re-derived from the immutable
finished journal on each GET. The only degraded platform is a legacy Telegram client
predating `downloadFile`, where the GCG falls back to the old clipboard copy and the
image option is not offered.
The alphabet-on-the-wire transport does **not** touch this invariant: the live edge
exchanges alphabet indices, but the persisted journal (and everything derived from it —