docs: audit housekeeping hotel workflows

This commit is contained in:
Simo committed 2026-08-25 18:26:25 +02:00
1 parent 4d9845b52f
commit 949e14c109
2 files changed
+779

No files matched your search

@@ -0,0 +1,120 @@
import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import { ownedLegacyPages } from "./discover-legacy-pages";
import { hotelMigrationEntries } from "./hotel";
import { validateMigrationEntries } from "./validate-matrix";
const HOTEL_PREFIXES = [
"/admin/rooms",
"/admin/navigation",
"/admin/radio",
"/admin/studio",
] as const;
describe("hotelMigrationEntries", () => {
it("maps all hotel tools below the hotel target root", () => {
expect(
validateMigrationEntries(
ownedLegacyPages(HOTEL_PREFIXES),
hotelMigrationEntries,
),
).toEqual([]);
expect(
hotelMigrationEntries.every(
(row) =>
row.targetPath === null || row.targetPath.startsWith("/admin/hotel/"),
),
).toBe(true);
});
it("preserves room ids while merging only the detail aliases", () => {
expect(
hotelMigrationEntries
.filter((row) => row.legacyPath.startsWith("/admin/rooms"))
.map(({ legacyPath, targetPath, decision }) => ({
legacyPath,
targetPath,
decision,
})),
).toEqual([
{
legacyPath: "/admin/rooms",
targetPath: "/admin/hotel/rooms",
decision: "REBUILD",
},
{
legacyPath: "/admin/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
},
{
legacyPath: "/admin/rooms/:id/furni",
targetPath: "/admin/hotel/rooms/:id/furni",
decision: "REBUILD",
},
{
legacyPath: "/admin/rooms/edit/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
},
{
legacyPath: "/admin/rooms/show/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
},
]);
});
it("keeps every audited workflow planned without parity claims", () => {
expect(
hotelMigrationEntries.every(
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
it("requires privileged audit and an explicit capability for every mutation", () => {
const mutationRows = hotelMigrationEntries.filter(
(row) => row.dependencies.mutations.length > 0,
);
expect(mutationRows.length).toBeGreaterThan(0);
expect(
mutationRows.every(
(row) =>
row.capabilities.mutate.length > 0 &&
row.auditRequirement === "PRIVILEGED_MUTATION",
),
).toBe(true);
});
it("records the actual permissions for room, radio, and Studio mutations", () => {
expect(hotelMigrationEntries).toContainEqual(
expect.objectContaining({
legacyPath: "/admin/rooms/edit/:id",
capabilities: {
read: [PERMS.ROOMS_EDIT],
mutate: [PERMS.ROOMS_EDIT, PERMS.ROOMS_DELETE],
},
}),
);
expect(hotelMigrationEntries).toContainEqual(
expect.objectContaining({
legacyPath: "/admin/radio/api-keys",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
}),
);
expect(hotelMigrationEntries).toContainEqual(
expect.objectContaining({
legacyPath: "/admin/studio/sync",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
}),
);
});
});
@@ -0,0 +1,659 @@
import { PERMS } from "@/lib/permission-slugs";
import type { MigrationEntry } from "./types";
type PlannedHotelEntry = Omit<
MigrationEntry,
"targetDomain" | "requiredTests" | "parityEvidence" | "status" | "notes"
> & {
requiredTests?: MigrationEntry["requiredTests"];
notes?: MigrationEntry["notes"];
};
function plannedHotelEntry(entry: PlannedHotelEntry): MigrationEntry {
return {
...entry,
targetDomain: "hotel",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
export const hotelMigrationEntries: readonly MigrationEntry[] = [
// Batch 1: room directory, consolidated room detail, furniture, and navigator.
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/rooms",
sourceFile: "src/app/admin/rooms/page.tsx",
targetPath: "/admin/hotel/rooms",
decision: "REBUILD",
capabilities: { read: [PERMS.ROOMS_VIEW], mutate: [] },
dependencies: {
queries: ["fetchAdminList", "Rooms", "GET /api/admin/export?type=rooms"],
mutations: [],
},
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/rooms/:id",
sourceFile: "src/app/admin/rooms/[id]/page.tsx",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
capabilities: { read: [PERMS.ROOMS_VIEW], mutate: [] },
dependencies: { queries: [], mutations: [] },
auditRequirement: "NONE",
localization: "COMPLETE",
accessibility: "COMPLETE",
requiredTests: ["e2e"],
notes: ["Redirect-only alias for the room detail workflow"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/rooms/:id/furni",
sourceFile: "src/app/admin/rooms/[id]/furni/page.tsx",
targetPath: "/admin/hotel/rooms/:id/furni",
decision: "REBUILD",
capabilities: {
read: [PERMS.ROOMS_VIEW],
mutate: [PERMS.ROOMS_EDIT],
},
dependencies: {
queries: ["Items", "ItemsBase", "Rooms", "User", "loadRoom"],
mutations: [
"bulkDeleteRoomItems",
"deleteRoomItem",
"RCON kickall",
"RCON reloadroom",
"roomRconAction",
"updateRoomItem",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Preserve the furniture suffix and room id in the target route"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/rooms/edit/:id",
sourceFile: "src/app/admin/rooms/edit/[id]/page.tsx",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.ROOMS_EDIT],
mutate: [PERMS.ROOMS_EDIT, PERMS.ROOMS_DELETE],
},
dependencies: {
queries: ["Rooms", "User", "loadRoom"],
mutations: [
"deleteRoom",
"RCON kickall",
"RCON reloadroom",
"RCON updateroom",
"roomRconAction",
"updateRoom",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Merge editing and RCON controls into the room detail workflow"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/rooms/show/:id",
sourceFile: "src/app/admin/rooms/show/[id]/page.tsx",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
capabilities: { read: [PERMS.ROOMS_VIEW], mutate: [] },
dependencies: { queries: ["Rooms", "User", "loadRoom"], mutations: [] },
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Merge the canonical read-only detail alias without changing its id",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/navigation",
sourceFile: "src/app/admin/navigation/page.tsx",
targetPath: "/admin/hotel/navigation",
decision: "REBUILD",
capabilities: { read: [PERMS.PAGES_VIEW], mutate: [] },
dependencies: {
queries: [
"NavigatorFlatcats",
"NavigatorPubliccats",
"navigator_publics raw SQL",
"Rooms",
],
mutations: [],
},
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
// Batch 2: radio overview, monitoring, moderation, and runtime configuration.
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio",
sourceFile: "src/app/admin/radio/page.tsx",
targetPath: "/admin/hotel/radio/overview",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["RadioApplications", "RadioSchedules", "RadioShouts"],
mutations: ["deleteShout"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/api-keys",
sourceFile: "src/app/admin/radio/api-keys/page.tsx",
targetPath: "/admin/hotel/radio/api-keys",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["RadioApiKeys"],
mutations: ["createApiKey", "deleteApiKey", "toggleApiKey"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"API-key generation and lifecycle changes are credential mutations",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/autodj",
sourceFile: "src/app/admin/radio/autodj/page.tsx",
targetPath: "/admin/hotel/radio/autodj",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["RadioAutoDjPlaylist"],
mutations: ["createTrack", "deleteTrack", "toggleTrack"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/banners",
sourceFile: "src/app/admin/radio/banners/page.tsx",
targetPath: "/admin/hotel/radio/banners",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["RadioBanners"],
mutations: [
"createRadioBanner",
"deleteRadioBanner",
"updateRadioBanner",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/embed",
sourceFile: "src/app/admin/radio/embed/page.tsx",
targetPath: "/admin/hotel/radio/embed",
decision: "REBUILD",
capabilities: { read: [PERMS.RADIO_VIEW], mutate: [] },
dependencies: {
queries: ["resolveHotelName", "siteSettings.get"],
mutations: [],
},
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/history",
sourceFile: "src/app/admin/radio/history/page.tsx",
targetPath: "/admin/hotel/radio/history",
decision: "REBUILD",
capabilities: { read: [PERMS.RADIO_VIEW], mutate: [] },
dependencies: { queries: ["RadioHistory", "User"], mutations: [] },
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/moderation",
sourceFile: "src/app/admin/radio/moderation/page.tsx",
targetPath: "/admin/hotel/radio/moderation",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["RadioShouts"],
mutations: ["deleteShout"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Shout deletion is a radio moderation mutation"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/monitoring",
sourceFile: "src/app/admin/radio/monitoring/page.tsx",
targetPath: "/admin/hotel/radio/monitoring",
decision: "REBUILD",
capabilities: { read: [PERMS.RADIO_VIEW], mutate: [] },
dependencies: {
queries: [
"fetch radio_listeners_api_url",
"fetch radio_now_playing_api_url",
"siteSettings.get",
],
mutations: [],
},
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Monitoring probes operator-configured external HTTP endpoints"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/points",
sourceFile: "src/app/admin/radio/points/page.tsx",
targetPath: "/admin/hotel/radio/points",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["siteSettings.get", "WebsiteSetting"],
mutations: ["savePoints", "siteSettings.reload"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/ranks",
sourceFile: "src/app/admin/radio/ranks/page.tsx",
targetPath: "/admin/hotel/radio/ranks",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["RadioRanks"],
mutations: ["createRadioRank", "deleteRadioRank", "updateRadioRank"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/radio/settings",
sourceFile: "src/app/admin/radio/settings/page.tsx",
targetPath: "/admin/hotel/radio/settings",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
mutate: [PERMS.RADIO_EDIT],
},
dependencies: {
queries: ["WebsiteSetting"],
mutations: [
"saveRadioSetting",
"saveRadioSettings",
"siteSettings.reload",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Settings include external-service credentials, runtime flags, webhooks, and custom code",
],
}),
// Batch 3: Studio audit and asset import workflows.
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio",
sourceFile: "src/app/admin/studio/page.tsx",
targetPath: "/admin/hotel/studio/furni",
decision: "MERGE",
capabilities: { read: [PERMS.ASSETS_IMPORT], mutate: [] },
dependencies: { queries: [], mutations: [] },
auditRequirement: "NONE",
localization: "COMPLETE",
accessibility: "COMPLETE",
requiredTests: ["e2e"],
notes: ["Redirect-only entry into the Studio furniture workflow"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/audit",
sourceFile: "src/app/admin/studio/audit/page.tsx",
targetPath: "/admin/hotel/studio/audit",
decision: "REBUILD",
capabilities: { read: [PERMS.ASSETS_IMPORT], mutate: [] },
dependencies: {
queries: ["POST /api/admin/import/audit", "runCatalogAudit"],
mutations: [],
},
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"The POST endpoint performs a read-only database and filesystem audit",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/badges",
sourceFile: "src/app/admin/studio/badges/page.tsx",
targetPath: "/admin/hotel/studio/badges",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT, PERMS.CATALOG_EDIT],
},
dependencies: {
queries: [
"GET /api/admin/import/badges",
"getBadgeData",
"searchBadges",
"WebsiteBadges",
],
mutations: [
"importBadgeSynced",
"POST /api/admin/import/badges",
"updateBadge",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Imports external badge assets into the configured gamedata filesystem",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/clone",
sourceFile: "src/app/admin/studio/clone/page.tsx",
targetPath: "/admin/hotel/studio/clone",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: [
"GET /api/admin/import/clone",
"GET /api/admin/import/clone/icon",
"getCloneList",
"listSources",
],
mutations: [
"DELETE /api/admin/import/clone",
"POST /api/admin/import/clone",
"POST /api/admin/import/clone/batch",
"cloneSingleFurni",
"rcon.updateCatalog",
"rcon.updateItems",
"syncAssetsToGamedataBundle",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Clone imports combine external HTTP, database, filesystem, and RCON mutations",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/clothing",
sourceFile: "src/app/admin/studio/clothing/page.tsx",
targetPath: "/admin/hotel/studio/clothing",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: [
"GET /api/admin/import/clothing",
"GET /api/admin/import/clothing/sets",
"getClothingSetList",
"getFigureList",
],
mutations: [
"DELETE /api/admin/import/clothing",
"POST /api/admin/import/clothing/batch",
"POST /api/admin/import/clothing/sets/batch",
"importClothingSet",
"importSingleFigure",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Clothing imports download and delete asset files"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/effects",
sourceFile: "src/app/admin/studio/effects/page.tsx",
targetPath: "/admin/hotel/studio/effects",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: ["GET /api/admin/import/effects", "getEffectList"],
mutations: [
"DELETE /api/admin/import/effects",
"importSingleEffect",
"POST /api/admin/import/effects/batch",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Effect imports download and delete asset files"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/furni",
sourceFile: "src/app/admin/studio/furni/page.tsx",
targetPath: "/admin/hotel/studio/furni",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: [
"GET /api/admin/import/clone",
"GET /api/admin/import/furni",
"getHabboGamedataHotel",
"getTreeFlat",
"previewAutoCatalog",
"siteSettings.getBool",
],
mutations: [
"deleteImportedFurni",
"PATCH /api/admin/import/furni",
"POST /api/admin/import/furni",
"POST /api/admin/import/furni/batch",
"PUT /api/admin/import/furni/nitro-editor",
"rcon.updateCatalog",
"rcon.updateItems",
"setFurnidataTranslateEnabled",
"syncAssetsToGamedataBundle",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Furniture imports combine official Habbo HTTP sources, catalog and item tables, asset files, and RCON reloads",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/maintenance",
sourceFile: "src/app/admin/studio/maintenance/page.tsx",
targetPath: "/admin/hotel/studio/maintenance",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_EDIT],
mutate: [PERMS.CATALOG_EDIT],
},
dependencies: {
queries: ["getFurniHealthAction", "previewAlignIdsAction"],
mutations: [
"applyAlignIdsAction",
"fixCatalogOffersAction",
"fixEverythingAction",
"fixSpriteIdsAction",
"reconcileIdsAction",
"removeDuplicateItemsBaseAction",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["The current page relies on action-level catalog-edit enforcement"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/pets",
sourceFile: "src/app/admin/studio/pets/page.tsx",
targetPath: "/admin/hotel/studio/pets",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: [
"GET /api/admin/import/pets",
"GET /api/admin/import/pets/icon",
"getPetList",
],
mutations: [
"DELETE /api/admin/import/pets",
"importSinglePet",
"POST /api/admin/import/pets/batch",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Pet imports download and delete asset files"],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/repair-icons",
sourceFile: "src/app/admin/studio/repair-icons/page.tsx",
targetPath: "/admin/hotel/studio/repair-icons",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: [],
mutations: [
"POST /api/admin/import/furni/repair-icons",
"repairMissingIcons",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Repairs icon files from local bundles or configured external sources",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/sync",
sourceFile: "src/app/admin/studio/sync/page.tsx",
targetPath: "/admin/hotel/studio/sync",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: ["ItemsBase", "listSources"],
mutations: [
"appendFurniEntriesBatch",
"cloneSingleFurni",
"POST /api/admin/import/clone/sync-all",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Full source sync mutates item data and asset files from external clone sources",
],
}),
plannedHotelEntry({
surface: "admin",
legacyPath: "/admin/studio/upload",
sourceFile: "src/app/admin/studio/upload/page.tsx",
targetPath: "/admin/hotel/studio/upload",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
mutate: [PERMS.ASSETS_IMPORT],
},
dependencies: {
queries: [],
mutations: ["POST /api/admin/import/furni/upload", "uploadSingleFurni"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Uploads mutate database, catalog, FurnitureData, and asset files"],
}),
];