From 4ed3c8ae581ca145bf8ed69ffcba7615b847781e Mon Sep 17 00:00:00 2001 From: codex Date: Wed, 26 Aug 2026 21:58:30 +0200 Subject: [PATCH] refactor(catalog): make template artwork fully local --- docs/PROJECT-STATE.md | 1 + docs/operations/local-templates.md | 5 ++ docs/security/security-and-threat-model.md | 2 +- internal/catalog/template.go | 26 ++++++- internal/catalog/template_test.go | 17 +++++ internal/persistence/sqlite/catalog.go | 22 ++++-- internal/persistence/sqlite/catalog_test.go | 5 ++ internal/persistence/sqlite/schema.sql | 1 + internal/persistence/sqlite/store.go | 36 +++++++++- internal/web/server.go | 75 +++++++++++++++++++-- internal/web/server_test.go | 16 ++++- tools/validate_spec.py | 3 + 12 files changed, 191 insertions(+), 18 deletions(-) diff --git a/docs/PROJECT-STATE.md b/docs/PROJECT-STATE.md index ce0e40e..7e671c5 100644 --- a/docs/PROJECT-STATE.md +++ b/docs/PROJECT-STATE.md @@ -62,6 +62,7 @@ Read this compact operational baseline before starting a milestone. Open detaile - Label values support only the explicit allowlist in `internal/instance/container_config.go`; unknown variables are errors, not arbitrary templates. - `{{game.icon_url}}` is the public icon for the game. `{{instance.slug}}` remains supported. - Template game artwork contains separate required local `logo` and horizontal `image` assets; template validation rejects missing files. Deployment previews expose distinct logo and artwork URLs while retaining `icon_url` as a compatible logo alias. Palworld template `1.1.0` is the first snapshot with this contract. +- All official and local template artwork is bundled locally, served through generic template-scoped routes with detected raster Content-Type, and retained in SQLite snapshots for historical rendering. Remote, absolute, traversal and escaping-symlink asset paths are rejected; no artwork checksum is required. - Embedded catalog validation is collection-based: every discovered template is schema- and cross-field-validated, including referenced assets, declared template-local integration modules and ports/configuration. A module bundle lives at `