Commit Graph
1766 Commits
Author SHA1 Message Date
openhands 0d943fe3dc fix(ci): use runs-on: ubuntu-latest (non-empty) for Gitea Actions v5
CI / check (push) Successful in 32s
CI / tests-integration (push) Successful in 2m4s
CI / tests-unit (push) Successful in 2m18s
CI / preflight (push) Skipped
CI / tests-ui (push) Successful in 3m2s
CI / deploy (push) Successful in 3m12s
2026-10-12 20:05:56 +02:00
openhands 6e82a02e64 fix(ci): rewrite ci.yaml with correct Gitea Actions syntax
CI / check (push) Failing after 1s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-12 20:04:13 +02:00
openhands 08ff14d0ac test: trigger CI run for monitoring
CI / check (push) Failing after 1s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / preflight (push) Skipped
Test Runner / hello (push) Failing after 2s
CI / tests-ui (push) Skipped
CI / deploy (push) Skipped
2026-10-12 20:01:17 +02:00
openhands b17da6ab25 fix(gitea): use runs-on: [] so host runner picks up jobs (contract test aligned)
CI / check (push) Failing after 1s
Test Runner / hello (push) Failing after 0s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-12 19:43:34 +02:00
openhands 56ca775405 fix(gitea): runner label ubuntu-latest (remove GITEA_TOKEN drop-in conflict)
Test Runner / hello (push) Successful in 2s
CI / check (push) Successful in 33s
CI / tests-integration (push) Successful in 1m57s
CI / tests-unit (push) Failing after 2m0s
CI / tests-ui (push) Successful in 2m43s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-12 19:38:08 +02:00
openhands 8ee99e8ce8 test: ubuntu-latest only label
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:26:16 +02:00
openhands 5ea1d50ad1 test: add ubuntu-latest label test
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:24:54 +02:00
openhands 6ef7486ca4 test: clean v5 install via Docker approach
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:21:39 +02:00
openhands 7c15cfd26d test: clean v5 install test
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:19:31 +02:00
openhands 2ca277d858 test: final CI test after clean install
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:17:52 +02:00
openhands 758e25452d test: try different label approach
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:13:19 +02:00
openhands 60d375144d test: final CI trigger test
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:12:03 +02:00
openhands 1c816019b1 test: final CI verification
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:09:59 +02:00
openhands ceff6f98d9 test: add test-ci file for CI trigger
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:09:01 +02:00
openhands 8395e60f87 test: fourth verification after token fix
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
2026-10-12 19:07:43 +02:00
openhands a92b951540 test: token sync fix verification
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 19:06:50 +02:00
openhands d5938f94ed test: second verification
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
2026-10-12 19:05:45 +02:00
openhands 991328ff0e test: verify runner picks up Gitea CI
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
2026-10-12 19:02:45 +02:00
openhands 1835221096 fix: remove .gitlab-ci.yml (using Gitea CI instead)
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
2026-10-12 19:00:45 +02:00
openhands e7a6245ac2 test: add test line to README
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
2026-10-12 18:49:25 +02:00
openhands da43b6c80c fix: use explicit runner label self-hosted:host to match registered v5-runner
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 18:28:31 +02:00
openhands eb67424a1c test: add verification comment to .gitlab-ci.yml, triggering workflow run
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 18:25:05 +02:00
openhands 3776475db4 fix: ci-workflow-contract test expectations updated to runs-on: []
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 18:18:24 +02:00
openhands 54b9186e52 fix: test.yml runs-on ubuntu-latest → [] for host runner compatibility
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 18:15:58 +02:00
openhands fe684faf70 fix: change Gitea Actions runner from self-hosted to host runner, preventing stuck jobs when self-hosted runners are offline
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 18:08:08 +02:00
openhands 22f834ef45 fix: add explicit runner tags to .gitlab-ci.yml jobs, ensuring shared runners are used and 'no matching online runner' error is prevented
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
2026-10-12 17:46:36 +02:00
openhands 7b249a7222 P1-P3 admin cleanup: rank guard, SSRF guard, count caching, dead code removal, pagination rewrite
CI / check (push) Canceled after 0s
CI / tests-unit (push) Canceled after 0s
CI / tests-integration (push) Canceled after 0s
Gitea Actions Runner Test / test-job (push) Canceled after 0s
CI / tests-ui (push) Canceled after 0s
CI / preflight (push) Canceled after 0s
CI / deploy (push) Canceled after 0s
Gitea Runner Clean Test / test-job (push) Canceled after 0s
- P1: new src/lib/admin/rank-guard.ts with tryGuardRank/guardRank + RankGuardTarget/Result; extracted from users.ts; applied to admin-bans (create/lift + rank redirect) and admin-badges (caps + rank guard + error surfacing); import-url-safety.ts SSRF guard wired into clone save+icon fetch; logAudit await in help-tickets; antiddos mutations SETTINGS_EDIT; markAllAlertsRead NOTIFICATIONS_EDIT; rankError/saveError in all 25 message files; tests rew/new for bans/badges/rank-guard/import-url-safety

- P2: ticket-inbox merged pagination reworked to single UNION ALL SQL with LIMIT/OFFSET (avoids O(offset) materialization); getCachedAdminCount with cacheFiltered option applied to devops/errors/photos/items/guilds/help-tickets/moderation pages; admin-theme catches→?error=1+banner+25 locales; logger in silent catches (rare-values/writeable-boxes); catalog-items-loader CAST→plain equality; count caching helper extended with opt-in cacheFiltered

- P3: removed dead modules is-staff/notice/recent-furni-resync/log-filters plus load-user-sanctions/user-sanction-timeline; removed orphaned CATALOG_PAGE_COLUMNS re-export; removed getFurniIconUrl from studio-furni-icons

Build: lint 0, typecheck 0, 3480 tests pass, i18n:check exit 0, colors exit 0. Circular chunk warning (9452/10535/66463) is webpack code-splitting artifact; build succeeds.
2026-10-12 17:42:19 +02:00
openhands 57529fd1ea Fix: badge API now reads from Gamedata/c_images/album1584
CI / check (push) Successful in 30s
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-unit (push) Successful in 1m46s
CI / tests-integration (push) Successful in 1m38s
Gitea Runner Clean Test / test-job (push) Successful in 2s
CI / tests-ui (push) Successful in 2m26s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m18s
The badge GIF files exist at /var/www/Gamedata/c_images/album1584/ but the
/api/imaging/badge endpoint only looked in /swf/c_images/album1584/ (relative
to process.cwd()). Added GEDATA_IMAGES_BASE candidate and fetchCandidate
handler so badges render correctly in the admin UI and on the site.
2026-10-11 21:14:10 +02:00
openhands acbb833eca Fix: make live test describe blocks conditional on RUN env vars (skip when not set)
CI / check (push) Successful in 32s
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-unit (push) Successful in 1m25s
CI / tests-integration (push) Successful in 1m17s
Gitea Runner Clean Test / test-job (push) Successful in 3s
CI / tests-ui (push) Successful in 2m9s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m46s
2026-10-11 20:49:53 +02:00
openhands 6912669754 Remove skip directives from live test files
CI / check (push) Successful in 36s
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-unit (push) Failing after 1m47s
CI / tests-integration (push) Successful in 1m28s
Gitea Runner Clean Test / test-job (push) Successful in 2s
CI / tests-ui (push) Successful in 2m11s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-11 20:26:27 +02:00
openhands 7388ad3451 Fix: admin badges formatting (biome)
CI / check (push) Successful in 34s
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / tests-unit (push) Successful in 1m33s
CI / tests-integration (push) Successful in 1m22s
Gitea Runner Clean Test / test-job (push) Successful in 2s
CI / tests-ui (push) Successful in 2m22s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m58s
2026-10-11 20:05:27 +02:00
openhands b13c9f47be Fix admin-badges: handle non-positive userId, truncate badge code to 32 chars, only revalidate on grant
CI / check (push) Failing after 23s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 3s
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 2s
2026-10-11 20:04:06 +02:00
openhands f14a0e5fe7 Fix i18n type errors: add colIcon to Dutch locale and type casts
CI / check (push) Successful in 31s
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-unit (push) Failing after 1m22s
CI / tests-integration (push) Successful in 1m19s
Gitea Runner Clean Test / test-job (push) Successful in 2s
CI / tests-ui (push) Successful in 2m12s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-11 19:56:05 +02:00
openhands 505ed2bfe2 fix(lint): remove duplicate colIcon key in en.json
CI / check (push) Failing after 30s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 2s
2026-10-11 19:40:32 +02:00
openhands 548ae541b2 fix(i18n): add colIcon keys for badges and rareValues
CI / check (push) Failing after 24s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 3s
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 2s
2026-10-11 19:40:03 +02:00
openhands 05883b1ee6 chore: make workflow file anonymous and secure
CI / check (push) Failing after 24s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / preflight (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-ui (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 3s
2026-10-11 19:38:22 +02:00
openhands ad015e1e9c fix(lint): remove duplicate i18n key and cleanup unused biome suppressions
CI / check (push) Failing after 24s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 2s
2026-10-11 19:36:57 +02:00
openhands 62e3e49ad1 fix(i18n): add colIcon translation to en.json
CI / check (push) Failing after 22s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 2s
2026-10-11 19:36:02 +02:00
openhands 338591691f chore: schone start test-workflow voor v5 runner
CI / check (push) Failing after 24s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Runner Clean Test / test-job (push) Successful in 12s
2026-10-11 19:34:04 +02:00
openhands f56109836e chore: trigger v5 runner
CI / check (push) Failing after 23s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 0s
test.yml (push) Invalid workflow file
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-11 19:31:35 +02:00
openhands b1a45902b4 Test Gitea v5 runner
CI / check (push) Failing after 24s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 1s
test.yml (push) Invalid workflow file
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-11 19:30:03 +02:00
openhands 7d8874c8cd fix: biome lint suppressions + admin-badges.ts formatting
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / check (push) Failing after 23s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-11 18:48:26 +02:00
openhands a06db72c65 Update: admin panel fixes, badge icons, studio improvements, gitea runner v5
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / check (push) Failing after 21s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
2026-10-11 18:44:02 +02:00
openhands afc8909d3f fix(studio): the furniture list was rendered at opacity 0 and never painted
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / check (push) Successful in 33s
CI / tests-integration (push) Successful in 2m2s
CI / tests-unit (push) Successful in 2m3s
CI / tests-ui (push) Successful in 2m39s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m40s
The Studio furniture pane was present in the DOM the whole time and still
looked empty. Every row existed, had real dimensions, and its image loaded
with a 200 — and none of it was visible.

The pane was wrapped in a `motion/react-m` element declared with
`initial={{ opacity: 0 }}` and `animate={{ opacity: 1 }}`. That minimal entry
renders the element but never runs the animation, so the inline style stayed at
opacity 0 and the content was painted transparently forever. Measured on the
live release: the table sat at opacity 1 directly inside a wrapper pinned at
`style="opacity: 0"`.

It went unnoticed because playwright.ui.config.ts sets reducedMotion to
"reduce", under which the animation is skipped and the element lands straight
on its final value. The existing Studio specs therefore passed while the real
browser showed nothing. That also means the perf win from the minimal entry
was never actually delivering a working fade — it only hid the breakage.

The decorative 150ms fade is now a CSS animation (.studio-list-fade-in). A CSS
animation cannot strand content this way: if it never runs, the element is
simply opaque. motion/react-m had exactly one usage in the app and is gone;
the four files that use the full motion/react are untouched and unaffected.

Adds e2e/ui/studio-visibility.spec.ts, which opts out of reduced motion and
asserts no ancestor of a furniture row is faded below 0.9. Verified it fails
on the old code with `Received: 0` and passes on the new, so this cannot
regress silently again.
2026-10-11 18:05:13 +02:00
openhands 990ebdb158 fix(pwa): retire the service worker instead of just fixing it
Gitea Actions Runner Test / test-job (push) Successful in 2s
CI / check (push) Successful in 35s
CI / tests-integration (push) Successful in 1m58s
CI / tests-unit (push) Successful in 2m22s
CI / tests-ui (push) Successful in 2m50s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m50s
The previous commit stopped the worker from caching build output, which
removed the cause of the blank Catalog Studio but left the worker itself
serving a purpose worth one offline fallback: three public endpoints
(/api/home, /api/online, /api/radio/config). Behind Cloudflare, for a site
whose visitors are online, that fallback rarely fires and goes stale exactly
where it is most likely to matter.

So the worker goes away rather than staying as a mostly-inert layer that every
future release still has to keep correct.

public/sw.js is not deleted, because deleting it would leave every existing
registration alive and still in control of the page, caching as it did before.
It becomes the opposite of what it was: on activate it deletes every cache,
unregisters itself and reloads open clients so they stop being controlled.
Browsers that already installed a worker therefore uninstall it on their next
visit; browsers that never had one are unaffected.

src/components/pwa-register.tsx is removed and unmounted from the root
layout, so nothing registers a worker any more and the kill switch only ever
runs for the visitors who need it.

The manifest is deliberately untouched. src/app/manifest.ts is an ordinary
Next.js route, independent of any worker, and Chrome installs from a manifest
alone, so the site stays installable on a phone.

Verified nothing depended on it: no other navigator.serviceWorker or caches.*
reference exists in the app, the theme runs from the plain /scripts/
theme-init.js script, and no Studio, catalog or import module touches a
worker. Typecheck and lint clean, 2326 unit tests and 72 UI tests green,
including every Studio and catalog spec.
2026-10-11 17:31:15 +02:00
openhands 1a4888df50 fix(pwa): stop the service worker replaying chunks from a previous release
Gitea Actions Runner Test / test-job (push) Successful in 3s
CI / check (push) Successful in 32s
CI / tests-integration (push) Successful in 2m11s
CI / tests-unit (push) Successful in 2m16s
CI / preflight (push) Skipped
CI / tests-ui (push) Successful in 2m54s
CI / deploy (push) Successful in 2m47s
The Catalog Studio rendered as a blank white page after a deploy, while the
server was serving it correctly: /admin/studio/furni answered 200 with 110KB
of HTML and every API it calls answered 200 with data. No script chunk 404ed
during the session and no JavaScript threw, so the failure was entirely in
what the browser chose to execute.

The service worker wrapped /assets/ and /_next/static/ in a Cache Storage
entry served cache-first, under a hardcoded name (atom-v3) with no build id
and no revalidation. A release therefore could not invalidate it: the browser
kept replaying the previous release's chunks against the new HTML, and React
never hydrated. The chunk branch also had no .catch(), unlike the API branch
below it, so a rejected fetch silently dropped the <script> instead of
surfacing a network error the browser could retry.

That cache also bought nothing. nginx already sends /_next/static/ and
/assets/ as `max-age=31536000, immutable`, and those filenames are
content-hashed, so the HTTP cache is both sufficient and safe — a changed
file gets a new name. The worker was the only layer able to go stale across a
deploy, and it was the one doing it.

Both prefixes now fall through to the network and are left to the HTTP cache.
The API offline fallback and network-first navigations are unchanged, and the
cache names move to v4 so an existing worker is replaced. SW_VERSION moves
with them: it is part of the registration URL, so without the bump the browser
never refetches sw.js and the old worker keeps running.

Unrelated but confirmed while tracing this: /assets/images/themes/arctic-ice.png
is requested by the browser and 404s, but that string exists nowhere in the
code, the database or the build. It was a stale reference served out of this
same cache, not a missing asset.
2026-10-11 17:21:53 +02:00
openhands 2978483ea9 fix(assets): serve furniture icons from the gamedata tree, add stack-height SQL generator
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 30s
CI / tests-integration (push) Successful in 1m52s
CI / tests-unit (push) Successful in 2m3s
CI / tests-ui (push) Successful in 2m40s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m47s
Commit the two changes that were live in the working tree but never
recorded.

The nginx change adds a location for /swf/dcr/hof_furni/icons/ that reads
/var/www/Gamedata/icons/ off disk and falls back to the CMS bundle for
anything missing. The CMS built its icon URLs from that path, but the icons
actually live in the gamedata tree: of the 16,263 classnames in items_base,
15,338 are present there under the safe name, against 11,267 under
public/swf/dcr/hof_furni/icons. The swf tree also keeps colour variants
behind a literal "*" in the filename, so every request using the safe name
missed, and hof.furni.url already points the Nitro client at the gamedata
tree. A miss is a no-store 404, never a cached one — same reasoning as
@gamedata_missing, since add_header without "always" says nothing about a
404 and Cloudflare would otherwise apply the zone TTL.

scripts/generate-stack-height-sql.ts emits a SQL file that repairs
items_base dimensions and interaction columns from the logic inside each
bundle, which is where they actually live rather than in furnidata. It
writes a file and touches no database, so the result is reviewed before it
is run.
2026-10-11 17:01:53 +02:00
openhands 43742e8d99 fix(catalog): decode WebP bundle textures so furniture icons resolve again
Every write path normalises a bundle's texture to WebP Lossless, so the
catalog icon was being read back with a PNG-only decoder. decodePng throws
on anything that is not a PNG, the callers caught that and returned null,
and the user-visible result was "no icon (not in source or bundle)" for
every furniture whose source does not serve a standalone icon.

Measured against the production asset tree, all 18,505 bundles were WebP;
icon extraction succeeded on 0 of them. src/lib/services/imager/
decode-texture.ts keeps PNG on the dependency-free decoder and routes WebP
through sharp, which is already a dependency and already encodes these
textures. extractFurniIconPng and getPetIconPng become async; the five
call sites (upload, clone import, furni import, icon repair and both icon
routes) already awaited their surrounding work.

Same root cause, second bug: the spritesheet frame key. Converters disagree
on packing — some keep a trailing ".png", and some lowercase the whole key
while leaving the bundle name mixed-case, so "LTD_fashionistaf" looks up
frame "LTD_fashionistaf_LTD_fashionistaf_icon_a" and never finds
"ltd_fashionistaf_ltd_fashionistaf_icon_a". Any mixed-case classname could
therefore never match, which is most of the catalogue. findFrame tries the
two exact spellings, then falls back to one case-insensitive pass.
Extraction now succeeds on 18,483 of 18,505 bundles (99.88%); the 22
remainder are data, not code — 9 bundles ship no icon asset, 11 do not
parse.

Third: three catalogue icons exist only as .gif while catalogueIconUrl
hardcoded .png, so the picker offered icons that could only ever 404, and
291 icons that ship as both formats were listed twice. The API now dedupes
per id and the two renderers retry with .gif before falling back to the
placeholder, matching what catalog-image-picker already did. Verified live:
/gamedata/.../icon_1542.png returns 404 while icon_1542.gif returns 200.

Separately, close the last hole in the memory cap. Every script in
package.json routes through scripts/with-memory-cap.sh, but invoking the
builder directly — from a terminal, an IDE or an agent — skipped the
wrapper and ran unbounded, on a host with no swap where the OOM killer
picks its victim across the whole machine. next.config.ts now refuses a
production build that the wrapper has not marked, before anything
allocates. next dev and next start are deliberately unaffected.

README gains a Memory-capped commands section covering the per-script
ceilings, the backends and the ulimit -v trap, and its stale version and
script tables are corrected.
2026-10-11 17:01:37 +02:00
openhands 6793f77733 fix(deploy): stub git status in the simulation harness
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 33s
CI / tests-integration (push) Successful in 1m37s
CI / tests-unit (push) Successful in 1m39s
CI / tests-ui (push) Successful in 2m20s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m6s
The clean-tree guard in ci-deploy.sh aborts the release when
`git status --porcelain` prints anything. The harness stubs `git` as a
shell function that only special-cases `rev-parse`; every other
subcommand fell through to its `ls-remote`-shaped printf, so `git status`
emitted a fake refs/heads/main line and the guard failed on every
scenario.

Introduced in fdb7af7e, which added the guard without teaching the
harness about it, so all 21 deploy tests have been failing since. This
stubs `status` to report a clean tree, and adds a scenario that asserts
the guard actually stops a release before it builds, migrates or starts
anything — the guard itself had no coverage, which is how it could break
silently in the first place.
2026-10-10 17:26:12 +02:00
openhands adffac7360 feat(catalog): store furniture bundles as .hab instead of .nitro
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 29s
CI / tests-unit (push) Failing after 1m37s
CI / tests-integration (push) Successful in 1m37s
CI / tests-ui (push) Successful in 2m17s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Every bundle the CMS writes — upload, clone, sync, repair and the pet /
effect / figure importers — now lands as `<classname>.hab`, the extension
this deployment's renderer asks for. `.hab` and `.nitro` are the same
container, so an upload of either extension is accepted.

Resolution goes through one module, src/lib/furni/bundle-file.ts, so
nothing has to know the extension twice. Every existence check probes
`.hab` first and falls back to `.nitro`: the on-disk asset set is still
predominantly `.nitro`, and without the fallback Studio would report every
imported item as missing and the cleanup scan would classify 18k live
bundles as fake leftovers. Downloads are unchanged — Habbo's CDN and every
configured clone source still serve `.nitro`, so the conversion happens on
write, not on request.

Deliberately unchanged: the staged-attachment store in furni-attachment.ts
keys on a UUID and never reaches the client, so renaming it would break
in-flight recovery jobs.

Adds scripts/migrate-nitro-to-hab.ts to rename the existing asset set. It
refuses to run without --dry-run or --yes, never overwrites an existing
.hab, never deletes, and is idempotent.

Note: renderer-config.json lives outside this repo and was patched to
.hab separately; that file is served with a 30-day max-age, so returning
clients need a cms-client cache purge to pick the change up.
2026-10-10 17:09:36 +02:00