Commit Graph

11 Commits

Author SHA1 Message Date
Ilia Denisov 132ed4e0db feat: load legary reports 2026-05-10 12:16:08 +02:00
Ilia Denisov 99962b295f tools/local-dev: legacy-report-to-json CLI for synthetic UI testing
A Go module under tools/local-dev/legacy-report that converts the
"dg" / "gplus" engine .REP files in tools/local-dev/reports/ into the
JSON shape of pkg/model/report.Report. The output drives a DEV-only
synthetic-mode loader on the UI lobby so the map, inspectors, and
order-overlay can be exercised against rich game states without
playing many turns end-to-end.

Scope is intentionally narrow: only the fields the UI client decodes
today (planets, players, own ship classes, header). Importing
pkg/model/report keeps the parser and the typed contract in lockstep
— any backwards-incompatible schema change breaks the tool's
compilation before it ships. The README spells out the parity rule
for extending the parser alongside future UI decoders.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 11:07:50 +02:00
Ilia Denisov e0e0f00daf chore: legacy reports 2026-05-10 10:41:59 +02:00
Ilia Denisov 6d6a384bee local-dev: auto-purge terminal Dev Sandbox games on every boot
Previously a cancelled / finished / start_failed sandbox game would
hang in the dev user's lobby until manually cleaned up — `make up`
would create a new running game alongside it but the dead tiles
piled up. Now backend's `devsandbox.Bootstrap` deletes every
terminal sandbox game owned by the dev user before find-or-create
runs, so the lobby always shows exactly one running tile.

Schema: `runtime_records` and `player_mappings` gain
`ON DELETE CASCADE` on their `game_id` foreign keys so a single
`DELETE FROM games` cleans every referencing row in one write.
Pre-prod migration rule applies — change goes into
`00001_init.sql`, not a new migration.

API: `lobby.Service.DeleteGame` is the new destructive helper that
backs the bootstrap purge. It bypasses the cancel-cascade-notify
pipeline; production callers must stay on the regular lifecycle.
The dev-sandbox docs in `tools/local-dev/README.md` spell out the
new behaviour.

Tests:
- backend/internal/lobby/lobby_e2e_test.go gains
  `TestDeleteGameCascadesEverything` proving CASCADE works
  end-to-end against a real Postgres testcontainer.
- backend/internal/devsandbox keeps its existing terminal-status
  contract test; the new `purgeTerminalSandboxGames` helper rides
  on the same `terminalSandboxStatus` predicate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 14:06:04 +02:00
Ilia Denisov 68d8607eaa local-dev: spell out compose rebuild after Go-side changes
The Phase 14 follow-up surfaced a footgun: `make up` reuses any
pre-built backend / gateway images and silently misses route table
or transcoder edits. Add a dedicated section to the README that
points at `make rebuild`, plus the engine-only path through
`make stop-engines` + `docker rmi`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 12:41:31 +02:00
Ilia Denisov 0f8f8698bd local-dev: rebuild dead sandbox + harden lobby card UX
Three fixes around the dev sandbox end-to-end path. Each one was
flushed out by an actual login walkthrough after the previous
commit.

Backend bootstrap now treats `cancelled`, `finished`, and
`start_failed` as terminal: the per-boot find-or-create skips such
games and provisions a fresh one. Without this, a single bad
shutdown cascade leaves the developer staring at a dead lobby tile
forever (cancelled games don't transition back). Covered by
TestTerminalSandboxStatus.

Tools/local-dev: stop killing engine containers in `make down`. The
runtime treats the disappearance of an engine as a real failure
(cascading the lobby game to `cancelled`); leaving the container
running across `down/up` lets the runtime reconciler re-attach on
the next boot. The teardown happens only in `make clean`, where the
DB is wiped anyway. Compose now also exposes :9090 (authenticated
EdgeGateway listener) on the host so the Vite dev proxy can reach
the Connect-Web surface, and bumps the gateway anti-abuse limits
for `public_misc` so the same surface is not blanket-rejected with
413.

Ui/frontend: the lobby's `My Games` cards are now clickable only
for the playable statuses (`running`, `paused`, `finished`). All
other statuses render as disabled buttons so a click on a draft or
cancelled game no longer drops the user on a 404 — the in-game
view at /games/:id/* doesn't exist before Phase 10 and never makes
sense for a cancelled game. Vite proxy splits the dev targets so
`/api/*` continues to talk to the REST listener and
`/galaxy.gateway.v1.EdgeGateway/*` is routed to the Connect-Web
listener via VITE_DEV_GRPC_PROXY_TARGET (defaults to :9090).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 19:32:44 +02:00
Ilia Denisov 82c4f70156 local-dev: stop spawned engine containers in down/clean
Backend's runtime spawns the engine container outside the compose
project, so `docker compose down` left a `galaxy-game-…` container
running. Add a `stop-engines` target that finds them by their OCI
image-title label (set in game/Dockerfile) and remove forcibly;
make `down` and `clean` depend on it. `clean` additionally wipes
the per-game state directory under /tmp/galaxy-game-state.

Add a troubleshooting note for the related symptom: when the
browser holds a keypair from a previous DB and `make clean`
recreates everything, the lobby renders "no games yet" until the
user clears site data or opens an incognito window. The dev user
keeps the same email but receives a fresh user_id, which the old
keypair cannot authenticate against.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 19:04:05 +02:00
Ilia Denisov e63748c344 local-dev: boot-time dev sandbox provisions a runnable game on up
Adds backend/internal/devsandbox: an idempotent boot-time hook that,
when BACKEND_DEV_SANDBOX_EMAIL is set, ensures (1) the configured
engine_version row, (2) the real dev user, (3) PlayerCount-1
deterministic dummy users, (4) a private "Dev Sandbox" game with a
year-out turn schedule, (5) memberships for every participant via
the new lobby.Service.InsertMembershipDirect helper, (6) a drive of
the lifecycle to running. Re-running on a populated DB is a no-op;
partial states from earlier crashes are recovered.

tools/local-dev gains the matching env vars in .env, surfaces them
in compose, and acquires a `make build-engine` target that builds
galaxy-engine:local-dev from game/Dockerfile (a prerequisite of
`up`/`rebuild`). The compose game-state mount is changed from a
named volume to a host bind on /tmp/galaxy-game-state so backend's
bind-mount source for spawned engine containers resolves on the
docker daemon.

After `make -C tools/local-dev up`, login as dev@local.test with
the dev code 123456 and the Dev Sandbox already shows up in My
Games. Per-user behaviour for the same email survives a backend
restart.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 15:51:09 +02:00
Ilia Denisov 6f6a854337 local-dev: Vite proxy for same-origin requests + upstream gateway Dockerfile fix
vite.config.ts now proxies `/api` and `/galaxy.gateway.v1.EdgeGateway`
to the gateway, so the browser sees only `localhost:5173` and never
trips a cross-origin preflight. `.env.development` accordingly points
`VITE_GATEWAY_BASE_URL` at the Vite origin. The proxy target is
overridable via `VITE_DEV_PROXY_TARGET=...` for non-default gateways
without touching the compose file.

`gateway/Dockerfile` previously failed to build because gateway
imports `galaxy/core` (replaced to `../ui/core` in `gateway/go.mod`)
but the Dockerfile did not copy `ui/core/` into the build context
nor declare the replace in the synthesised `go.work`. Adding both
makes `docker build -f gateway/Dockerfile .` succeed; this is the
same fix already shipped in `tools/local-dev/gateway.Dockerfile`,
back-ported to upstream.

Verified:
- docker build -f gateway/Dockerfile . — builds cleanly
- pnpm test 14/14, pnpm exec playwright test 44/44 (with CI=1 to
  force a fresh dev server; reuse keeps the previous startup env)
- curl POST through localhost:5173/api/* and /galaxy.gateway.v1.* —
  reach the gateway, no CORS preflight on the browser side

tools/local-dev/README.md updated with the new network map and the
`VITE_DEV_PROXY_TARGET` override.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 11:04:00 +02:00
Ilia Denisov 69fa6b30e1 tools/local-dev: docker-compose stack for UI development
Adds tools/local-dev/ with postgres + redis + mailpit + backend +
gateway plus a Make wrapper, so `make -C tools/local-dev up` brings
the full authenticated stack online and `pnpm -C ui/frontend dev`
talks to it directly. The committed `.env.development` already
points at the stack and pins the matching gateway response public
key from the dev keypair under tools/local-dev/keys/.

The backend ships a new opt-in env, BACKEND_AUTH_DEV_FIXED_CODE
(`tools/local-dev/.env` defaults it to 123456). When set,
ConfirmEmailCode accepts that literal in addition to the real
bcrypt-verified code; SendEmailCode still queues a real email so
Mailpit captures the issued code at http://localhost:8025/, and
both paths coexist. The override is rejected as non-six-digit by
config validation and emits a loud warning at backend startup.

The local-dev Dockerfiles mirror backend/Dockerfile and
gateway/Dockerfile but switch the runtime stage to alpine so
docker-compose healthchecks can wget /healthz; the gateway
Dockerfile additionally copies ui/core/ into the build context
because gateway/go.mod's `replace galaxy/core => ../ui/core` is
required to compile the gateway main.

Smoke tested:
- `make -C tools/local-dev up` boots all five services to healthy.
- send-email-code + confirm-email-code with code=123456 returns a
  device_session_id; a real code in Mailpit also redeems
  successfully.
- `pnpm test` 14/14, `pnpm exec playwright test` 44/44.
- `go test ./backend/internal/config/...` green.

Docs: tools/local-dev/README.md, tools/local-dev/keys/README.md,
new "Local development stack" section in ui/docs/testing.md, and a
short pointer in ui/README.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 09:42:29 +02:00
Ilia Denisov 7450006ed3 phase 2: ui testing infrastructure
Vitest + @testing-library/jest-dom matchers wired through tests/setup.ts.
Playwright with four projects: chromium-desktop, webkit-desktop,
chromium-mobile-iphone-13, chromium-mobile-pixel-5; traces and
screenshots retained on failure.

.gitea/workflows/ui-test.yaml runs Tier 1 on every push and pull
request: monorepo Go service tests (backend with -p 1 to dodge
testcontainer contention; gateway, game, every pkg/<name> module),
pnpm install --frozen-lockfile, playwright install --with-deps,
pnpm test, pnpm exec playwright test. Uploads playwright-report
and test-results on failure. Integration suite stays gated behind
make -C integration integration; deprecated client/ excluded.

.gitea/workflows/ui-release.yaml mirrors Tier 1 on v* tag push and
keeps commented placeholders for visual regression (Phase 33) and
macOS iOS smoke (Phase 32).

ui/docs/testing.md documents both tiers and the local invocations
that mirror what CI runs. ui/PLAN.md Phase 2 marked done; Phase 3
gains a bullet to extend the go test command with ./ui/core/...;
Phase 36 has the renamed release workflow path.

tools/local-ci/ ships a self-contained docker-compose for verifying
workflows against a local Gitea + arm64 act_runner before pushing
to a real instance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 08:24:44 +02:00