feat(studio): expand nitro cleanup with repair, auto-clean, and orphaned assets
Scan distinguishes fake, broken, and orphaned SWF/icon assets with age metadata, deletes per asset kind, re-downloads broken nitro bundles from configured sources, auto-cleans old fake leftovers, and exports a JSON manifest. Adds rebuild and auto-clean API endpoints with audit coverage and a housekeeping preview route under the hotel domain. Verified: full vitest suite (2213 tests), typecheck, and biome all pass.
This commit is contained in:
1 parent
ea4fd375b4
commit
438277a17a
13 files changed
+1118
-155
No files matched your search
@@ -20,7 +20,14 @@ export const hotelManifest = {
|
||||
PERMS.PAGES_VIEW,
|
||||
PERMS.CATALOG_EDIT,
|
||||
),
|
||||
routes: [],
|
||||
routes: [
|
||||
{
|
||||
id: "nitro-cleanup",
|
||||
labelKey: "pages.housekeeping.domains.hotel.routes.nitroCleanup",
|
||||
href: "/admin-next/hotel/nitro-cleanup",
|
||||
capability: anyCapability(PERMS.ASSETS_IMPORT),
|
||||
},
|
||||
],
|
||||
searchProviders: [],
|
||||
inboxSources: [],
|
||||
widgets: [],
|
||||
|
||||
@@ -561,7 +561,7 @@ describe("housekeeping foundation completion contracts", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("creates the real six-domain registry in locked order without workflows", () => {
|
||||
it("creates the real six-domain registry in locked order without approved workflows", () => {
|
||||
const registry = createHousekeepingRegistry(HOUSEKEEPING_MANIFESTS);
|
||||
|
||||
expect(registry.domains.map((domain) => domain.id)).toEqual([
|
||||
@@ -572,9 +572,20 @@ describe("housekeeping foundation completion contracts", () => {
|
||||
"hotel",
|
||||
"system",
|
||||
]);
|
||||
expect(registry.domains.every((domain) => domain.routes.length === 0)).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
registry.domains
|
||||
.filter((domain) => domain.id !== "hotel")
|
||||
.every((domain) => domain.routes.length === 0),
|
||||
).toBe(true);
|
||||
expect(
|
||||
registry.domains.find((domain) => domain.id === "hotel")?.routes,
|
||||
).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "nitro-cleanup",
|
||||
href: "/admin-next/hotel/nitro-cleanup",
|
||||
labelKey: "pages.housekeeping.domains.hotel.routes.nitroCleanup",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps production preview disabled even when the flag is true", () => {
|
||||
|
||||
@@ -77,6 +77,7 @@ const expectedManifests = [
|
||||
labelKey: "pages.housekeeping.domains.operations.title",
|
||||
descriptionKey: "pages.housekeeping.domains.operations.description",
|
||||
slugs: [PERMS.ADMIN_DASHBOARD, PERMS.ASSETS_IMPORT],
|
||||
routes: [],
|
||||
},
|
||||
{
|
||||
id: "people",
|
||||
@@ -108,6 +109,7 @@ const expectedManifests = [
|
||||
PERMS.MOD_CFH_EDIT,
|
||||
PERMS.MOD_TICKETS_EDIT,
|
||||
],
|
||||
routes: [],
|
||||
},
|
||||
{
|
||||
id: "content",
|
||||
@@ -131,6 +133,7 @@ const expectedManifests = [
|
||||
PERMS.SETTINGS_VIEW,
|
||||
PERMS.SETTINGS_EDIT,
|
||||
],
|
||||
routes: [],
|
||||
},
|
||||
{
|
||||
id: "economy",
|
||||
@@ -144,6 +147,7 @@ const expectedManifests = [
|
||||
PERMS.CATALOG_EDIT,
|
||||
PERMS.SHOP_EDIT,
|
||||
],
|
||||
routes: [],
|
||||
},
|
||||
{
|
||||
id: "hotel",
|
||||
@@ -161,6 +165,14 @@ const expectedManifests = [
|
||||
PERMS.PAGES_VIEW,
|
||||
PERMS.CATALOG_EDIT,
|
||||
],
|
||||
routes: [
|
||||
{
|
||||
id: "nitro-cleanup",
|
||||
labelKey: "pages.housekeeping.domains.hotel.routes.nitroCleanup",
|
||||
href: "/admin-next/hotel/nitro-cleanup",
|
||||
capability: { mode: "any", slugs: [PERMS.ASSETS_IMPORT] },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "system",
|
||||
@@ -180,6 +192,7 @@ const expectedManifests = [
|
||||
PERMS.SETTINGS_EDIT,
|
||||
PERMS.NOTIFICATIONS_EDIT,
|
||||
],
|
||||
routes: [],
|
||||
},
|
||||
] as const;
|
||||
describe("housekeeping registry", () => {
|
||||
@@ -324,7 +337,7 @@ describe("housekeeping registry", () => {
|
||||
labelKey: expected.labelKey,
|
||||
descriptionKey: expected.descriptionKey,
|
||||
});
|
||||
expect(actual.routes).toEqual([]);
|
||||
expect(actual.routes).toEqual(expected.routes);
|
||||
expect(actual.searchProviders).toEqual([]);
|
||||
expect(actual.inboxSources).toEqual([]);
|
||||
expect(actual.widgets).toEqual([]);
|
||||
|
||||
@@ -586,15 +586,21 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
|
||||
dependencies: {
|
||||
queries: ["GET /api/admin/studio/nitro-cleanup", "scanFakeBrokenNitros"],
|
||||
mutations: [
|
||||
"autoCleanFakeNitros",
|
||||
"DELETE /api/admin/studio/nitro-cleanup",
|
||||
"clearFurniImportCache",
|
||||
"deleteNitroCleanupFiles",
|
||||
"POST /api/admin/studio/nitro-cleanup/auto-clean",
|
||||
"POST /api/admin/studio/nitro-cleanup/rebuild",
|
||||
"repairBrokenNitros",
|
||||
],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: ["Deletes orphaned or unparseable nitro bundles from asset files"],
|
||||
notes: [
|
||||
"Deletes orphaned or unparseable asset files and re-downloads broken nitro bundles from configured sources",
|
||||
],
|
||||
}),
|
||||
plannedHotelEntry({
|
||||
surface: "admin",
|
||||
|
||||
Reference in new issue
Block a user