ARCHITECTURE.md §15 "Verification order" specifies signature verification
(step 4) before payload_hash (step 5), but the authenticated-edge
decorator chain wrapped the payload-hash gate outside the signature gate,
so the hash was checked first. gateway/README.md and gateway/docs/flows.md
had drifted to match the code (hash-first), leaving ARCHITECTURE.md as the
lone source describing the intended order.
Swap the two decorators in server.go so the signature gate runs first, and
align README + flows.md to ARCHITECTURE.md. Signature-first is the
cryptographically sound order: the signature covers the payload_hash field,
so the request is authenticated before any of its content is processed.
Observable side effect: a request carrying a tampered payload_hash whose
signature was computed over the original hash is now rejected at the
signature gate (UNAUTHENTICATED "invalid request signature") instead of the
hash gate (INVALID_ARGUMENT). Security is unchanged — both refusals happen
before the payload is handled. The four payload-hash unit tests re-sign
over the tampered hash so they keep exercising the hash gate; the
cross-service integration test signs over the overridden hash and already
accepts both codes.
Refs #39
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Serve the whole stack behind one host: site at /, game UI at /game/,
gateway REST at /api + /healthz, Connect at /rpc (prefix stripped by the
edge Caddy). The built artifact is domain-agnostic — the UI talks to the
gateway same-origin via relative URLs, so the same bundle runs under any
host with no rebuild and with CORS disabled.
- Rename the Connect proto service galaxy.gateway.v1.EdgeGateway ->
edge.v1.Gateway; regenerate Go + TS; public path /rpc/edge.v1.Gateway.
- Move the game UI under base path /game (env BASE_PATH); make the
manifest, service-worker scope, WASM loader, and all navigation
base-aware via a withBase helper.
- Relative API + /rpc Connect prefix; Vite dev proxy mirrors the strip.
- Rewrite the edge Caddy (dev + prod) for path-based routing; empty CORS
allow-lists (same-origin); single host.
- New VitePress project site (site/): i18n en/ru with switcher, LaTeX
math, minimal monospace theme; built and served at /.
- dev-deploy compose/Makefile + CI (dev-deploy, prod-build, new
site-build) build and seed the site; probes hit /, /game/, /healthz.
- Sync docs (ARCHITECTURE, gateway README/openapi, dev-deploy &
local-dev READMEs, CLAUDE.md, ui/PLAN).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>