From 3a03a3db151f58cc7de928791bd3efd1812759d7 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 24 Aug 2026 22:07:38 +0200 Subject: [PATCH] docs: audit housekeeping economy workflows --- .../housekeeping/migration/economy.test.ts | 55 +++ .../housekeeping/migration/economy.ts | 421 ++++++++++++++++++ 2 files changed, 476 insertions(+) create mode 100644 src/features/housekeeping/migration/economy.test.ts create mode 100644 src/features/housekeeping/migration/economy.ts diff --git a/src/features/housekeeping/migration/economy.test.ts b/src/features/housekeeping/migration/economy.test.ts new file mode 100644 index 0000000000..280403ad23 --- /dev/null +++ b/src/features/housekeeping/migration/economy.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it } from "vitest"; +import { ownedLegacyPages } from "./discover-legacy-pages"; +import { economyMigrationEntries } from "./economy"; +import { validateMigrationEntries } from "./validate-matrix"; + +const ECONOMY_PREFIXES = [ + "/admin/catalog", + "/admin/items", + "/admin/shop", + "/admin/marketplace", + "/admin/transactions", + "/admin/vouchers", + "/admin/subscriptions", + "/admin/rare-values", + "/admin/badges", + "/admin/achievements", + "/admin/sounds", + "/admin/calendar", +] as const; + +describe("economyMigrationEntries", () => { + it("covers every economy page without legacy-domain targets", () => { + const expected = ownedLegacyPages(ECONOMY_PREFIXES); + expect(validateMigrationEntries(expected, economyMigrationEntries)).toEqual( + [], + ); + expect( + economyMigrationEntries.every( + (row) => + row.targetPath === null || + row.targetPath.startsWith("/admin/economy/"), + ), + ).toBe(true); + }); + + it("keeps every audited workflow planned without parity claims", () => { + expect( + economyMigrationEntries.every( + (row) => row.status === "PLANNED" && row.parityEvidence.length === 0, + ), + ).toBe(true); + }); + + it("requires privileged audit for economy mutations", () => { + const mutationRows = economyMigrationEntries.filter( + (row) => row.dependencies.mutations.length > 0, + ); + expect(mutationRows.length).toBeGreaterThan(0); + expect( + mutationRows.every( + (row) => row.auditRequirement === "PRIVILEGED_MUTATION", + ), + ).toBe(true); + }); +}); diff --git a/src/features/housekeeping/migration/economy.ts b/src/features/housekeeping/migration/economy.ts new file mode 100644 index 0000000000..20be791cb2 --- /dev/null +++ b/src/features/housekeeping/migration/economy.ts @@ -0,0 +1,421 @@ +import { PERMS } from "@/lib/permission-slugs"; +import type { MigrationEntry } from "./types"; + +type PlannedEconomyEntry = Omit< + MigrationEntry, + "targetDomain" | "requiredTests" | "parityEvidence" | "status" | "notes" +> & { + requiredTests?: MigrationEntry["requiredTests"]; + notes?: MigrationEntry["notes"]; +}; + +function plannedEconomyEntry(entry: PlannedEconomyEntry): MigrationEntry { + return { + ...entry, + targetDomain: "economy", + requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"], + parityEvidence: [], + status: "PLANNED", + notes: entry.notes ?? [], + }; +} + +export const economyMigrationEntries: readonly MigrationEntry[] = [ + // Batch 1: catalog pages, Builder Club, maintenance, and base items. + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/catalog", + sourceFile: "src/app/admin/catalog/page.tsx", + targetPath: "/admin/economy/catalog", + decision: "MERGE", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: [ + "CatalogItems", + "CatalogItemsBc", + "CatalogPages", + "CatalogPagesBc", + "GET /api/admin/catalog/items", + "GET /api/admin/catalog/tree", + "getCatalogItemCounts", + ], + mutations: [ + "createBcPage", + "createCatalogPage", + "DELETE /api/admin/catalog/tree", + "deleteBcTreePage", + "deleteCatalogPage", + "deleteTreePage", + "fixEverythingAction", + "PATCH /api/admin/catalog/tree", + "reorderBcTreePage", + "reorderTreePage", + "toggleBcPage", + "toggleCatalogPage", + "updateBcPage", + "updateCatalogPage", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + notes: [ + "Merge the overlapping table, tree, and visual-manager editors into one catalog workflow", + ], + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/catalog/:id", + sourceFile: "src/app/admin/catalog/[id]/page.tsx", + targetPath: "/admin/economy/catalog/:id", + decision: "MERGE", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: [ + "CatalogPages", + "GET /api/admin/catalog/suggest", + "GET /api/admin/furni/search", + "getAncestors", + "loadCatalogItemsData", + ], + mutations: [ + "bulkCreateCatalogItems", + "createCatalogItem", + "deleteCatalogItems", + "deleteCatalogPage", + "moveCatalogItems", + "reorderCatalogItems", + "translateCatalogItems", + "updateCatalogItem", + "updateCatalogPage", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + notes: [ + "Merge the detail tabs with the collection-level visual editor while preserving the page id", + ], + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/catalog/builder-club", + sourceFile: "src/app/admin/catalog/builder-club/page.tsx", + targetPath: "/admin/economy/catalog", + decision: "MERGE", + capabilities: { read: [PERMS.CATALOG_VIEW], mutate: [] }, + dependencies: { queries: [], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "COMPLETE", + requiredTests: ["e2e"], + notes: ["Redirect-only entry into the Builder Club catalog view"], + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/catalog/builder-club/:id", + sourceFile: "src/app/admin/catalog/builder-club/[id]/page.tsx", + targetPath: "/admin/economy/catalog/builder-club/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: ["CatalogItemsBc", "CatalogPagesBc"], + mutations: [ + "createBcItem", + "deleteBcItem", + "updateBcItem", + "updateBcPage", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/catalog/maintenance", + sourceFile: "src/app/admin/catalog/maintenance/page.tsx", + targetPath: "/admin/economy/catalog/maintenance", + decision: "REBUILD", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: ["getFurniHealthAction", "previewAlignIdsAction"], + mutations: [ + "applyAlignIdsAction", + "fixCatalogOffersAction", + "fixEverythingAction", + "fixSpriteIdsAction", + "reconcileIdsAction", + "removeDuplicateItemsBaseAction", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/items", + sourceFile: "src/app/admin/items/page.tsx", + targetPath: "/admin/economy/items", + decision: "REBUILD", + capabilities: { read: [PERMS.CATALOG_VIEW], mutate: [] }, + dependencies: { queries: ["fetchAdminList", "ItemsBase"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/items/:id", + sourceFile: "src/app/admin/items/[id]/page.tsx", + targetPath: "/admin/economy/items/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: ["ItemsBase"], + mutations: ["updateItemsBase"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + + // Batch 2: commerce products, listings, vouchers, and subscriptions. + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/shop", + sourceFile: "src/app/admin/shop/page.tsx", + targetPath: "/admin/economy/commerce/shop", + decision: "REBUILD", + capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] }, + dependencies: { + queries: ["WebsitePaypalTransactions", "WebsiteShopArticles"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/shop/new", + sourceFile: "src/app/admin/shop/new/page.tsx", + targetPath: "/admin/economy/commerce/shop/new", + decision: "REBUILD", + capabilities: { + read: [PERMS.SHOP_EDIT], + mutate: [PERMS.SHOP_EDIT], + }, + dependencies: { queries: [], mutations: ["createShopArticle"] }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/shop/:id", + sourceFile: "src/app/admin/shop/[id]/page.tsx", + targetPath: "/admin/economy/commerce/shop/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.SHOP_VIEW], + mutate: [PERMS.SHOP_EDIT], + }, + dependencies: { + queries: ["WebsiteShopArticles"], + mutations: ["deleteShopArticle", "updateShopArticle"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/marketplace", + sourceFile: "src/app/admin/marketplace/page.tsx", + targetPath: "/admin/economy/commerce/marketplace", + decision: "REBUILD", + capabilities: { + read: [PERMS.SHOP_VIEW], + mutate: [PERMS.SHOP_EDIT], + }, + dependencies: { + queries: ["MarketplaceItems", "User"], + mutations: ["cancelMarketplaceListing"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/vouchers", + sourceFile: "src/app/admin/vouchers/page.tsx", + targetPath: "/admin/economy/commerce/vouchers", + decision: "REBUILD", + capabilities: { + read: [PERMS.SHOP_VIEW], + mutate: [PERMS.SHOP_EDIT], + }, + dependencies: { + queries: ["WebsiteShopVouchers"], + mutations: ["createVoucher", "deleteVoucher"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/subscriptions", + sourceFile: "src/app/admin/subscriptions/page.tsx", + targetPath: "/admin/economy/commerce/subscriptions", + decision: "REBUILD", + capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] }, + dependencies: { queries: ["users_subscriptions"], mutations: [] }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + notes: ["Current route reads users_subscriptions through raw SQL"], + }), + + // Batch 3: transaction history and rare-value configuration. + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/transactions", + sourceFile: "src/app/admin/transactions/page.tsx", + targetPath: "/admin/economy/history/transactions", + decision: "REBUILD", + capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] }, + dependencies: { + queries: ["User", "WebsitePaypalTransactions"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/rare-values", + sourceFile: "src/app/admin/rare-values/page.tsx", + targetPath: "/admin/economy/value/rare-values", + decision: "REBUILD", + capabilities: { + read: [PERMS.SHOP_VIEW], + mutate: [PERMS.SHOP_EDIT], + }, + dependencies: { + queries: ["WebsiteRareValueCategories", "WebsiteRareValues"], + mutations: [ + "createCategory", + "createValue", + "deleteCategory", + "deleteValue", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + + // Batch 4: badges, achievements, soundtracks, and calendar rewards. + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/badges", + sourceFile: "src/app/admin/badges/page.tsx", + targetPath: "/admin/economy/rewards/badges", + decision: "REBUILD", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: ["WebsiteBadges"], + mutations: ["giveBadge", "uploadBadge"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/achievements", + sourceFile: "src/app/admin/achievements/page.tsx", + targetPath: "/admin/economy/rewards/achievements", + decision: "REBUILD", + capabilities: { read: [PERMS.CATALOG_VIEW], mutate: [] }, + dependencies: { queries: ["Achievements"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/sounds", + sourceFile: "src/app/admin/sounds/page.tsx", + targetPath: "/admin/economy/rewards/sounds", + decision: "REBUILD", + capabilities: { + read: [PERMS.CATALOG_VIEW], + mutate: [PERMS.CATALOG_EDIT], + }, + dependencies: { + queries: ["CatalogItems", "siteSettings.get", "Soundtracks"], + mutations: [ + "deleteSoundtrack", + "POST /api/admin/sounds/upload", + "updateSoundtrack", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/calendar", + sourceFile: "src/app/admin/calendar/page.tsx", + targetPath: "/admin/economy/rewards/calendar", + decision: "REBUILD", + capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] }, + dependencies: { + queries: ["CalendarCampaigns", "CalendarRewards"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedEconomyEntry({ + surface: "admin", + legacyPath: "/admin/calendar/:id", + sourceFile: "src/app/admin/calendar/[id]/page.tsx", + targetPath: "/admin/economy/rewards/calendar/:id", + decision: "REBUILD", + capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] }, + dependencies: { + queries: ["CalendarCampaigns", "CalendarRewards"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), +];