diff --git a/docs/superpowers/plans/2026-08-02-furni-import-hotel-source.md b/docs/superpowers/plans/2026-08-02-furni-import-hotel-source.md new file mode 100644 index 00000000..67f876bd --- /dev/null +++ b/docs/superpowers/plans/2026-08-02-furni-import-hotel-source.md @@ -0,0 +1,111 @@ +# Furni Import Hotel Source Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make the furni import visibly and consistently use the CMS `habbo_gamedata_hotel` setting without Italy-specific names or messages. + +**Architecture:** Keep locale selection centralized in `getHabboGamedataHotel()` and expose normalized display metadata to the server-rendered import page. Rename the furnidata cache contract to generic official-Habbo terminology, and keep asset downloads on the global `images.habbo.com` CDN. + +**Tech Stack:** TypeScript 7, React 19, Next.js 16, Vitest 4. + +## Global Constraints + +- `habbo_gamedata_hotel` remains the single source of truth. +- Furnidata and external texts use `www.habbo.`. +- SWF and icon downloads remain on `images.habbo.com`. +- Cache entries must never leak across two configured hotels. +- Existing import behavior and permissions remain unchanged. + +--- + +### Task 1: Generic official-Habbo furnidata contract + +**Files:** +- Create: `src/lib/services/habbo-furnidata-cache.test.ts` +- Modify: `src/types/furni.ts` +- Modify: `src/lib/services/habbo-furnidata-cache.ts` +- Modify: `src/lib/services/habbofurni.ts` +- Modify: `src/lib/services/furni-data.ts` +- Modify: `src/lib/services/furni-import.ts` +- Modify: `src/actions/admin-settings.ts` +- Modify: `src/app/api/admin/import/furni/route.ts` +- Modify: `src/app/api/admin/import/furni/resync/route.ts` +- Modify: `src/app/api/admin/import/furni/batch-regen/route.ts` + +**Interfaces:** +- Produces: `OfficialHabboFurniEntry`. +- Produces: `getOfficialHabboFurnidata()`, `lookupOfficialHabboFurni()`, and `clearOfficialHabboFurnidataCache()`. +- Consumes: `getHabboGamedataHotel()` and `habboFurnidataUrl(hotel)`. + +- [ ] **Step 1: Write a failing cache-isolation test** + +Mock the selected hotel as `it` for the first request and `nl` for the second. Return distinct fixtures from `fetch` and assert that the second call returns the Dutch fixture and requests `https://www.habbo.nl/gamedata/furnidata_json/1`. + +- [ ] **Step 2: Run the cache test and verify RED** + +Run: `pnpm exec vitest run --coverage=false src/lib/services/habbo-furnidata-cache.test.ts` + +Expected: FAIL because the generic official-Habbo API is not exported yet. + +- [ ] **Step 3: Rename the cache contract and consumers** + +Rename the Italy-specific type and functions throughout the import pipeline. Keep the existing hotel-keyed cache behavior and update comments to say “configured official Habbo hotel”. + +- [ ] **Step 4: Run the cache test and verify GREEN** + +Run: `pnpm exec vitest run --coverage=false src/lib/services/habbo-furnidata-cache.test.ts` + +Expected: PASS with separate `it` and `nl` fetches. + +### Task 2: Display and report the configured source + +**Files:** +- Create: `src/app/admin/import/furni/import-source.test.ts` +- Create: `src/app/admin/import/furni/import-source.ts` +- Modify: `src/app/admin/import/furni/page.tsx` +- Modify: `src/app/admin/import/furni/import-furni-client.tsx` +- Modify: `src/lib/services/furni-import.ts` +- Modify: `src/lib/services/furni-import.test.ts` + +**Interfaces:** +- Produces: `FurniImportSource { hotel, label, host, furnidataUrl }`. +- Produces: `getFurniImportSource()` for the server page. +- Produces: `formatOfficialHabboEnrichmentWarning(hotel, name)`. + +- [ ] **Step 1: Write failing source and message tests** + +Assert that an `nl` setting becomes `{ hotel: "nl", label: "Netherlands (habbo.nl)", host: "habbo.nl", furnidataUrl: "https://www.habbo.nl/gamedata/furnidata_json/1" }` and that enrichment reports `Enriched from habbo.nl`. + +- [ ] **Step 2: Run the tests and verify RED** + +Run: `pnpm exec vitest run --coverage=false src/app/admin/import/furni/import-source.test.ts src/lib/services/furni-import.test.ts` + +Expected: FAIL because source metadata and the dynamic warning formatter do not exist. + +- [ ] **Step 3: Implement source metadata and UI** + +Read the normalized hotel on the server page, pass source metadata into `ImportFurniClient`, and render a compact source badge/link above the furni controls. Replace literal `habbo.it` enrichment wording with the resolved host. + +- [ ] **Step 4: Run focused verification** + +Run: `pnpm exec vitest run --coverage=false src/lib/services/habbo-furnidata-cache.test.ts src/app/admin/import/furni/import-source.test.ts src/lib/services/furni-import.test.ts` + +Expected: PASS. + +- [ ] **Step 5: Run repository verification** + +Run: + +```text +pnpm typecheck +pnpm test +pnpm build +``` + +Expected: all commands exit with status 0 using the same non-secret production validation environment as CI where required. + +- [ ] **Step 6: Commit the implementation** + +```text +fix: use configured Habbo hotel in furni import +```