diff --git a/README.md b/README.md index 2db166a..93b3812 100644 --- a/README.md +++ b/README.md @@ -62,35 +62,49 @@ and there is nothing to decide; several and the setup screen shows a picker. ```json [ - { "name": "Teletype Games", "catalogUrl": "https://teletypegames.org", "storeRepositoryUrl": null }, { - "name": "Some Other Store", - "catalogUrl": "https://games.example.org", - "storeRepositoryUrl": "https://git.example.org/stores/other-desktop-store" - } + "name": "Teletype Games", + "catalogUrl": "https://teletypegames.org", + "storeRepositoryUrl": "https://git.teletypegames.org/stores/ttg-desktop-store", + "config": { "store": { "id": "ttg" }, "paths": { "subfolder": "teletypegames" } } + }, + { "name": "Some Other Store", "catalogUrl": "https://games.example.org", + "storeRepositoryUrl": null, "config": null } ] ``` -**A store needs no repository of its own.** A name and a catalog are enough: the -store engine's built-in defaults already cover the host-to-asset mapping, the -install modes, the platforms and the behaviour, so what is actually missing from -them is identity — a slug, a name and a catalog URL — and that is exactly what a -registry record carries. With `storeRepositoryUrl` null the client writes a -three-section config and the store installs. +**A store needs nothing of its own.** A name and a catalog are enough: the store +engine's built-in defaults already cover the host-to-asset mapping, the install modes, +the platforms and the behaviour, so what is actually missing from them is identity — a +slug, a name and a catalog URL — and that is exactly what a registry record carries. +With `config` and `storeRepositoryUrl` both null the client writes a three-section +config and the store installs. -From a record the client works out the rest: +Where a store's configuration comes from, in the order the client asks: + +1. **`config` on the registry record** — the store's own configuration, in the same + shape a store's `config.json` had, because it is that file moved into the registry. + It costs no request: it arrived with the store list. +2. **`storeRepositoryUrl` → `…/raw/branch/master/config.json`** — the same thing in its + older home, read for a registry whose stores have not moved over yet. A repository + **without** a `config.json` is treated as no repository at all. +3. **the engine's defaults** — when there is neither. + +Two fields the record always decides, whatever the config says: -- **the store id** — which names the store home and the folder games land in — - comes from the repository name when there is one (`ttg-desktop-store` becomes - `ttg`), otherwise from the catalog host (`teletypegames.org` becomes - `teletypegames`), otherwise from the display name. A `config.json` that sets its - own id keeps it. - **`catalogUrl` and `name`** override the config's own `store.base_url` and `store.name`. The registry says which catalog this store is *for*, so it wins. -- **`storeRepositoryUrl`**, when given → the store's `config.json`, read from - `…/raw/branch/master/config.json`. That file stays the authority on how the store - behaves: which platforms, which statuses, where things land. A repository - **without** a `config.json` is treated as no repository at all. +- **the store id** — which names the store home and the folder games land in — comes + from the config's `store.id` when it sets one; otherwise from the repository name + (`ttg-desktop-store` becomes `ttg`), then the catalog host (`teletypegames.org` + becomes `teletypegames`), then the display name. + +**The window never supplies a config.** It is handed stores to show and hands one back +to install, but only as an identity: `RegistryStoreDtoMapper.toModel` drops the config, +and `StoreProvisioningService` reads the record again from the registry before +installing. A config decides where files are written and which subtree the store may +later delete from, so it must not be something the renderer can set — the same rule as +`GameDto` carrying no paths. What the defaults produce, for a record with no repository: the games land in a folder named after the store id, and released, archived **and demo** titles are diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3ece61b..25cee27 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,57 +1,29 @@ -# WarpEngine Client 2.0.0 +# WarpEngine Client 2.1.0 -**The store engine is part of the app. Nothing has to be installed on the machine any -more.** Reading the catalog, choosing which release fits your computer, downloading and -unpacking it, writing the menu entry and remembering what went where all happen inside -the application now. There is no Python to find, no child process, and no JSON protocol -between the two halves — which is why this is a major version rather than a feature. +**A store's configuration now comes from the registry itself.** `GET /api/stores` +records carry a `config` field — the same thing a store's `config.json` held, moved into +the record that already says what the store is. The client applies it directly, so +installing a store no longer depends on a second repository existing and staying +reachable, and a store can be configured entirely from the site's admin. -What that changes for a person: on Windows and on a fresh Mac the app simply works. -Before it looked for `python3`, `python` and `py -3`, and where none answered it drew a -screen with a link to python.org instead of a catalog. That screen is gone, along with -the one that offered to refresh a store engine too old to drive. +The old path still works. Where a record has no `config` but names a repository, the +client reads `…/raw/branch/master/config.json` from it exactly as before, so a registry +whose stores have not moved over is unaffected. With neither, the engine's defaults +carry the store, as they always have. The order is: registry config, then repository +file, then defaults. -**Your existing library is kept.** `config.json` and `state.json` on disk are unchanged — -the same field names, the same `:` keys, the same file modes — so a machine -whose games were installed by the shell store keeps them. Opening this version against -such a store lists them as installed, offers no needless update, and a sync reports -*already up to date*. A `version: 1` state file is still migrated on first read. - -The two Python files an earlier install left in the store folder are removed the next -time that store is set up. Nothing reads them, and a folder that still looks like it -holds the engine invites someone to run it against a state file this app is also writing. - -**The client knows which WarpEngine served a catalog.** Every WarpEngine API response -carries a `WarpEngine-Version` header, and the client now reads it, names the version in -the log, and picks the catalog dialect for it. `SUPPORTED_WARP_ENGINE_VERSIONS` lists what -this build was written against — 0.2, 0.3 and 0.4 — and the four cases are all handled: - -| The header says | What the client does | -|---|---| -| a supported version | reads the catalog with that version's dialect | -| nothing at all | reads it as the oldest supported version — an engine before 0.4.0 sent no header | -| something older | the same, and says so in the log | -| something newer | tries the newest dialect anyway, warning that titles may be missed | - -Adding a version to that list fails the build until somebody says what it reads like, in -the type checker and in the linter both. A new engine version cannot arrive unnoticed. - -**Refresh and the language picker are icons.** They sit together at the foot of the side -menu, and the *Actions* heading that used to head a section of one button is gone. Both -carry their name as a tooltip and to a screen reader, and the language picker is still a -real `