A store registry record needs no repository

The client only ever took identity from a store repository — a slug, a name, a catalog —
and the store engine's own defaults cover everything else: the host-to-asset mapping, the
install modes, the platforms, the behaviour. So `store_repository_url` is now optional:
nullable in the schema, no presence validation, the format check only when a value is
given, and the serializer answers null rather than an empty string, because the client
branches on its absence.

Adding a store is therefore a row with two fields filled in. Given a repository the
client still reads its config.json, and that file remains the authority on how the store
behaves — the admin form and the endpoint's documentation say so.

The frontend's /stores page gains a section of its own for the graphical client on the
desktop tab: what it does, that it sets the store up itself, that it is the way in on
Windows where `curl … | sh` does not exist, and links to the releases, the repository and
the documentation — now under stores/warp-engine-client, which is where that repository
lives after the rename.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 16:53:33 +02:00
co-authored by Claude Opus 5
parent 5517133e25
commit 466aeac6ca
12 changed files with 137 additions and 26 deletions
@@ -24,6 +24,14 @@ RSpec.describe Api::StoresController, type: :request do
expect(store["storeRepositoryUrl"]).to end_with("/stores/ttg-desktop-store")
end
it "answers null for a store with no repository" do
create(:store, store_repository_url: nil)
get "/api/stores"
expect(JSON.parse(response.body).first["storeRepositoryUrl"]).to be_nil
end
it "leaves out soft-deleted stores" do
create(:store, name: "Gone").update!(deleted_at: Time.current)
+7 -1
View File
@@ -3,7 +3,6 @@ require "rails_helper"
RSpec.describe Store, type: :model do
it { should validate_presence_of(:name) }
it { should validate_presence_of(:catalog_url) }
it { should validate_presence_of(:store_repository_url) }
it "rejects a catalog url that is not http(s)" do
store = build(:store, catalog_url: "git@example.org:thing.git")
@@ -15,6 +14,13 @@ RSpec.describe Store, type: :model do
expect(build(:store, store_repository_url: "not a url")).not_to be_valid
end
# A store without a repository is a complete store: the client takes identity
# from the record and everything else from the engine's defaults.
it "accepts a store with no repository at all" do
expect(build(:store, store_repository_url: nil)).to be_valid
expect(build(:store, store_repository_url: "")).to be_valid
end
describe ".ordered" do
it "lists stores by name" do
later = create(:store, name: "Zed Games")