0007: Immutable versioned game builds + a catalog indexed by the API
- Status: Accepted
- Date: 2026-10-13
Context
Games are static files. The hub needs a list of playable games with metadata, the API needs to know games exist (saves and scores reference them), and old builds may still be open on someone’s phone during an update.
Decision
tools/games-host(pnpm build) copies eachgames/<id>/distto.out/games/<id>/<version>/and writes.out/games/catalog.json(schema in@tohe/contract). Builds are immutable: a change requires a new version.- The games origin serves builds with
Cache-Control: immutableandcatalog.jsonwithno-cache. - The API’s Registry module polls
catalog.json(Registry:SyncInterval) and upserts itsregistry.gamestable. Games missing from the catalog are unlisted, never deleted, so their saves and scores stay valid. - The hub lists games from
GET /api/games, which returns absoluteentryUrls on the games origin. - One version per game is current. Old versions remain on disk until a cleanup policy is decided.
Consequences
- Rollback = rebuild the previous version; no cache invalidation is ever needed.
- The catalog is pull-based: a new game appears in the hub within one sync interval.
- A future “beta” channel can be added as a catalog field without changing the flow.
Alternatives considered
- Push registration (CI calls an admin endpoint): needs admin credentials in CI and an auth flow before M1.
- Hub reads catalog.json directly: skips the API, but the API must know games for saves, scores and per-profile visibility anyway.