docs: complete housekeeping migration matrix
This commit is contained in:
1 parent
9b7d5de12f
commit
3b3d7780c9
6 files changed
+634
-1
No files matched your search
+2
-1
@@ -21,7 +21,8 @@
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "tsx scripts/apply-migrations.ts",
|
||||
"db:migrate:status": "tsx scripts/apply-migrations.ts --status",
|
||||
"db:studio": "drizzle-kit studio"
|
||||
"db:studio": "drizzle-kit studio",
|
||||
"hk:matrix:check": "tsx scripts/verify-housekeeping-matrix.ts"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,jsx,tsx,json}": "biome check --write --no-errors-on-unmatched"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { discoverLegacyPages } from "../src/features/housekeeping/migration/discover-legacy-pages";
|
||||
import { HOUSEKEEPING_MIGRATION_MATRIX } from "../src/features/housekeeping/migration/matrix";
|
||||
import { validateMigrationEntries } from "../src/features/housekeeping/migration/validate-matrix";
|
||||
|
||||
const discovered = discoverLegacyPages();
|
||||
const issues = validateMigrationEntries(
|
||||
discovered,
|
||||
HOUSEKEEPING_MIGRATION_MATRIX,
|
||||
);
|
||||
|
||||
if (issues.length > 0) {
|
||||
for (const issue of issues) console.error(issue);
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
console.log(
|
||||
`Housekeeping migration matrix: ${HOUSEKEEPING_MIGRATION_MATRIX.length}/${discovered.length} valid`,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { discoverLegacyPages } from "./discover-legacy-pages";
|
||||
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
|
||||
import { validateMigrationEntries } from "./validate-matrix";
|
||||
|
||||
describe("HOUSEKEEPING_MIGRATION_MATRIX", () => {
|
||||
it("covers all 137 legacy pages exactly once", () => {
|
||||
const discovered = discoverLegacyPages();
|
||||
|
||||
expect(HOUSEKEEPING_MIGRATION_MATRIX).toHaveLength(137);
|
||||
expect(
|
||||
validateMigrationEntries(discovered, HOUSEKEEPING_MIGRATION_MATRIX),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("contains no undecided evidence markers", () => {
|
||||
expect(JSON.stringify(HOUSEKEEPING_MIGRATION_MATRIX)).not.toMatch(
|
||||
/TBD|TODO|FIXME|UNCLASSIFIED/,
|
||||
);
|
||||
});
|
||||
|
||||
it("is sorted by legacy path", () => {
|
||||
expect(HOUSEKEEPING_MIGRATION_MATRIX.map((row) => row.legacyPath)).toEqual(
|
||||
[...HOUSEKEEPING_MIGRATION_MATRIX.map((row) => row.legacyPath)].sort(
|
||||
(a, b) => a.localeCompare(b),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { contentMigrationEntries } from "./content";
|
||||
import { economyMigrationEntries } from "./economy";
|
||||
import { hotelMigrationEntries } from "./hotel";
|
||||
import { operationsMigrationEntries } from "./operations";
|
||||
import { peopleMigrationEntries } from "./people";
|
||||
import { systemMigrationEntries } from "./system";
|
||||
|
||||
export const HOUSEKEEPING_MIGRATION_MATRIX = [
|
||||
...operationsMigrationEntries,
|
||||
...peopleMigrationEntries,
|
||||
...contentMigrationEntries,
|
||||
...economyMigrationEntries,
|
||||
...hotelMigrationEntries,
|
||||
...systemMigrationEntries,
|
||||
].sort((a, b) => a.legacyPath.localeCompare(b.legacyPath));
|
||||
@@ -0,0 +1,128 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
import { ownedLegacyPages } from "./discover-legacy-pages";
|
||||
import { systemMigrationEntries } from "./system";
|
||||
import { validateMigrationEntries } from "./validate-matrix";
|
||||
|
||||
const SYSTEM_PREFIXES = [
|
||||
"/admin/alerts",
|
||||
"/admin/analytics",
|
||||
"/admin/commandocentrum",
|
||||
"/admin/devops",
|
||||
"/admin/emulator",
|
||||
"/admin/housekeeping",
|
||||
"/admin/logs",
|
||||
"/admin/maintenance",
|
||||
"/admin/menu",
|
||||
"/admin/permissions",
|
||||
"/admin/settings",
|
||||
] as const;
|
||||
|
||||
describe("systemMigrationEntries", () => {
|
||||
it("covers all 19 System pages exactly once", () => {
|
||||
expect(systemMigrationEntries).toHaveLength(19);
|
||||
expect(
|
||||
validateMigrationEntries(
|
||||
ownedLegacyPages(SYSTEM_PREFIXES),
|
||||
systemMigrationEntries,
|
||||
),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("removes legacy foundation-owned pages", () => {
|
||||
expect(systemMigrationEntries).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
legacyPath: "/admin/housekeeping",
|
||||
decision: "REMOVE",
|
||||
targetPath: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
legacyPath: "/admin/menu",
|
||||
decision: "REMOVE",
|
||||
targetPath: null,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps live permissions as a System workflow", () => {
|
||||
expect(systemMigrationEntries).toContainEqual(
|
||||
expect.objectContaining({
|
||||
legacyPath: "/admin/permissions",
|
||||
targetPath: "/admin/system/access/permissions",
|
||||
decision: expect.not.stringMatching("REMOVE"),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("retains the read-only legacy housekeeping value in removal notes", () => {
|
||||
const housekeeping = systemMigrationEntries.find(
|
||||
(row) => row.legacyPath === "/admin/housekeeping",
|
||||
);
|
||||
|
||||
expect(housekeeping?.dependencies.queries).toEqual(
|
||||
expect.arrayContaining([
|
||||
"exportPermissions",
|
||||
"getAuditLogs",
|
||||
"legacy ACL comparison",
|
||||
]),
|
||||
);
|
||||
expect(housekeeping?.notes.join(" ")).toMatch(
|
||||
/read-only.*export.*comparison/i,
|
||||
);
|
||||
});
|
||||
|
||||
it("uses only the approved System target roots", () => {
|
||||
const allowedRoots = [
|
||||
"/admin/system/access",
|
||||
"/admin/system/configuration",
|
||||
"/admin/system/observability",
|
||||
"/admin/system/operations",
|
||||
];
|
||||
|
||||
expect(
|
||||
systemMigrationEntries.every(
|
||||
(row) =>
|
||||
row.targetPath === null ||
|
||||
allowedRoots.some(
|
||||
(root) =>
|
||||
row.targetPath === root || row.targetPath?.startsWith(`${root}/`),
|
||||
),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps non-removal workflows planned without parity claims", () => {
|
||||
expect(
|
||||
systemMigrationEntries
|
||||
.filter((row) => row.decision !== "REMOVE")
|
||||
.every(
|
||||
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("records authoritative capabilities for privileged System mutations", () => {
|
||||
expect(systemMigrationEntries).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
legacyPath: "/admin/commandocentrum",
|
||||
capabilities: {
|
||||
read: [PERMS.RCON_EXECUTE],
|
||||
mutate: [PERMS.RCON_EXECUTE],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
legacyPath: "/admin/permissions/:id",
|
||||
capabilities: {
|
||||
read: [PERMS.PERMISSIONS_MANAGE],
|
||||
mutate: [PERMS.PERMISSIONS_MANAGE],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,442 @@
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
import type { MigrationEntry } from "./types";
|
||||
|
||||
type PlannedSystemEntry = Omit<
|
||||
MigrationEntry,
|
||||
"targetDomain" | "requiredTests" | "parityEvidence" | "status" | "notes"
|
||||
> & {
|
||||
requiredTests?: MigrationEntry["requiredTests"];
|
||||
notes?: MigrationEntry["notes"];
|
||||
};
|
||||
|
||||
function plannedSystemEntry(entry: PlannedSystemEntry): MigrationEntry {
|
||||
return {
|
||||
...entry,
|
||||
targetDomain: "system",
|
||||
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
|
||||
parityEvidence: [],
|
||||
status: "PLANNED",
|
||||
notes: entry.notes ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
export const systemMigrationEntries: readonly MigrationEntry[] = [
|
||||
// Operator alerts and read-only analytics.
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/alerts",
|
||||
sourceFile: "src/app/admin/alerts/page.tsx",
|
||||
targetPath: "/admin/system/operations/alerts",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.NOTIFICATIONS_VIEW],
|
||||
mutate: [PERMS.NOTIFICATIONS_EDIT, PERMS.NOTIFICATIONS_VIEW],
|
||||
},
|
||||
dependencies: {
|
||||
queries: ["AlertLogs"],
|
||||
mutations: [
|
||||
"markAllAlertsRead",
|
||||
"rcon.send hotelalert",
|
||||
"sendHotelAlert",
|
||||
],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: [
|
||||
"Marking alerts read and broadcasting a hotel alert use different current permission slugs",
|
||||
],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/analytics",
|
||||
sourceFile: "src/app/admin/analytics/page.tsx",
|
||||
targetPath: "/admin/system/observability/analytics",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.ANALYTICS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: [
|
||||
"Ban",
|
||||
"Rooms",
|
||||
"RoomTradeLog",
|
||||
"User",
|
||||
"chatlogs_room raw SQL",
|
||||
"redisCache",
|
||||
],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/analytics/activity",
|
||||
sourceFile: "src/app/admin/analytics/activity/page.tsx",
|
||||
targetPath: "/admin/system/observability/analytics/activity",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.ANALYTICS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: [
|
||||
"Ban",
|
||||
"User",
|
||||
"bans raw SQL",
|
||||
"chatlogs_room raw SQL",
|
||||
"commandlogs raw SQL",
|
||||
"redisCache",
|
||||
"users raw SQL",
|
||||
],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/analytics/economy",
|
||||
sourceFile: "src/app/admin/analytics/economy/page.tsx",
|
||||
targetPath: "/admin/system/observability/analytics/economy",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.ANALYTICS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: [
|
||||
"LogsShopPurchases",
|
||||
"MarketplaceItems",
|
||||
"RoomTradeLog",
|
||||
"User",
|
||||
"logs_shop_purchases raw SQL",
|
||||
"redisCache",
|
||||
],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
|
||||
// Runtime operations, health, and emulator configuration.
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/commandocentrum",
|
||||
sourceFile: "src/app/admin/commandocentrum/page.tsx",
|
||||
targetPath: "/admin/system/operations/command-center",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.RCON_EXECUTE],
|
||||
mutate: [PERMS.RCON_EXECUTE],
|
||||
},
|
||||
dependencies: {
|
||||
queries: [
|
||||
"EmulatorErrors",
|
||||
"StaffActivities",
|
||||
"User",
|
||||
"fetchOpsHealth",
|
||||
"fetchOpsOnlineUsers",
|
||||
"siteSettings.getBool",
|
||||
],
|
||||
mutations: [
|
||||
"alertUser",
|
||||
"disconnectUser",
|
||||
"executeCommand",
|
||||
"forwardUser",
|
||||
"giveBadge",
|
||||
"giveCredits",
|
||||
"giveDiamonds",
|
||||
"giveDuckets",
|
||||
"hotelAlert",
|
||||
"sendGift",
|
||||
"setMotto",
|
||||
"setRank",
|
||||
"updateCatalog",
|
||||
"updateNavigator",
|
||||
"updateWordFilter",
|
||||
],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: [
|
||||
"The current set-rank action combines RCON with a database update and rank-relative authorization",
|
||||
],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/devops",
|
||||
sourceFile: "src/app/admin/devops/page.tsx",
|
||||
targetPath: "/admin/system/observability/devops",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.DEVOPS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: [
|
||||
"EmulatorErrors",
|
||||
"EmulatorSettings",
|
||||
"GET /api/admin/devops/health",
|
||||
"fetchOpsHealth",
|
||||
],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: ["Health checks probe the database, Redis, RCON, and online users"],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/devops/errors",
|
||||
sourceFile: "src/app/admin/devops/errors/page.tsx",
|
||||
targetPath: "/admin/system/observability/devops/errors",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.DEVOPS_VIEW], mutate: [] },
|
||||
dependencies: { queries: ["EmulatorErrors"], mutations: [] },
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/emulator",
|
||||
sourceFile: "src/app/admin/emulator/page.tsx",
|
||||
targetPath: "/admin/system/configuration/emulator",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.SETTINGS_VIEW],
|
||||
mutate: [PERMS.SETTINGS_EDIT],
|
||||
},
|
||||
dependencies: {
|
||||
queries: ["EmulatorSettings", "EmulatorTexts"],
|
||||
mutations: ["updateEmulatorSetting", "updateEmulatorText"],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: ["The current actions upsert emulator-owned settings and texts"],
|
||||
}),
|
||||
|
||||
// Foundation-owned legacy pages are retired, not migrated as workflows.
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/housekeeping",
|
||||
sourceFile: "src/app/admin/housekeeping/page.tsx",
|
||||
targetPath: null,
|
||||
decision: "REMOVE",
|
||||
capabilities: { read: [PERMS.SETTINGS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: [
|
||||
"AclModelPermission",
|
||||
"AclPermission",
|
||||
"AclRole",
|
||||
"WebsiteHousekeepingPermissions",
|
||||
"exportPermissions",
|
||||
"getAuditLogs",
|
||||
"legacy ACL comparison",
|
||||
],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
requiredTests: ["integration", "e2e"],
|
||||
notes: [
|
||||
"Remove the legacy foundation surface while preserving its read-only export and ACL comparison value in the live access workflow",
|
||||
"Legacy housekeeping writes already redirect to live Permissions",
|
||||
],
|
||||
}),
|
||||
|
||||
// Staff, audit, chat, command, and trade observability.
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/logs",
|
||||
sourceFile: "src/app/admin/logs/page.tsx",
|
||||
targetPath: "/admin/system/observability/logs/staff",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
|
||||
dependencies: { queries: ["StaffActivities", "User"], mutations: [] },
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/logs/audit",
|
||||
sourceFile: "src/app/admin/logs/audit/page.tsx",
|
||||
targetPath: "/admin/system/observability/logs/audit",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
|
||||
dependencies: { queries: ["getAuditLogs"], mutations: [] },
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/logs/chat",
|
||||
sourceFile: "src/app/admin/logs/chat/page.tsx",
|
||||
targetPath: "/admin/system/observability/logs/chat",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: ["chatlogs_room raw SQL", "loadChatLogList", "users raw SQL"],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/logs/commands",
|
||||
sourceFile: "src/app/admin/logs/commands/page.tsx",
|
||||
targetPath: "/admin/system/observability/logs/commands",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: ["commandlogs raw SQL", "loadCommandLogList", "users raw SQL"],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/logs/trades",
|
||||
sourceFile: "src/app/admin/logs/trades/page.tsx",
|
||||
targetPath: "/admin/system/observability/logs/trades",
|
||||
decision: "REBUILD",
|
||||
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
|
||||
dependencies: {
|
||||
queries: ["loadTradeLogList", "room_trade_log raw SQL", "users raw SQL"],
|
||||
mutations: [],
|
||||
},
|
||||
auditRequirement: "NONE",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
}),
|
||||
|
||||
// Global configuration and access control.
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/maintenance",
|
||||
sourceFile: "src/app/admin/maintenance/page.tsx",
|
||||
targetPath: "/admin/system/operations/maintenance",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.SETTINGS_VIEW],
|
||||
mutate: [PERMS.SETTINGS_EDIT],
|
||||
},
|
||||
dependencies: {
|
||||
queries: ["WebsiteSetting"],
|
||||
mutations: ["saveMaintenance", "siteSettings.reload"],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: ["Maintenance changes global login availability and splash content"],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/menu",
|
||||
sourceFile: "src/app/admin/menu/page.tsx",
|
||||
targetPath: null,
|
||||
decision: "REMOVE",
|
||||
capabilities: {
|
||||
read: [PERMS.SETTINGS_VIEW],
|
||||
mutate: [PERMS.SETTINGS_EDIT],
|
||||
},
|
||||
dependencies: {
|
||||
queries: ["ADMIN_NAV_GROUPS", "siteSettings.get"],
|
||||
mutations: ["saveAdminNavConfig", "siteSettings.update"],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
requiredTests: ["integration", "e2e"],
|
||||
notes: [
|
||||
"Remove the manual legacy menu editor because foundation manifests own navigation",
|
||||
],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/permissions",
|
||||
sourceFile: "src/app/admin/permissions/page.tsx",
|
||||
targetPath: "/admin/system/access/permissions",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.PERMISSIONS_MANAGE],
|
||||
mutate: [PERMS.PERMISSIONS_MANAGE],
|
||||
},
|
||||
dependencies: {
|
||||
queries: ["fetchEmulatorRankSummaries", "users grouped by rank"],
|
||||
mutations: [
|
||||
"createRank",
|
||||
"deleteRank",
|
||||
"repairAdminNavAclGrants",
|
||||
"rcon.send updatepermissions",
|
||||
],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: ["Keep this live ACL and emulator-rank workflow in System access"],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/permissions/:id",
|
||||
sourceFile: "src/app/admin/permissions/[id]/page.tsx",
|
||||
targetPath: "/admin/system/access/permissions/:id",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.PERMISSIONS_MANAGE],
|
||||
mutate: [PERMS.PERMISSIONS_MANAGE],
|
||||
},
|
||||
dependencies: {
|
||||
queries: [
|
||||
"AclModelPermission",
|
||||
"AclPermission",
|
||||
"AclRole",
|
||||
"User",
|
||||
"fetchEmulatorRankForEdit",
|
||||
],
|
||||
mutations: [
|
||||
"AclRole load-time synchronization",
|
||||
"rcon.send updatepermissions",
|
||||
"saveRank",
|
||||
"setCmsPermissions",
|
||||
],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: [
|
||||
"The current route can create or retitle a CMS role while loading rank detail",
|
||||
],
|
||||
}),
|
||||
plannedSystemEntry({
|
||||
surface: "admin",
|
||||
legacyPath: "/admin/settings",
|
||||
sourceFile: "src/app/admin/settings/page.tsx",
|
||||
targetPath: "/admin/system/configuration/settings",
|
||||
decision: "REBUILD",
|
||||
capabilities: {
|
||||
read: [PERMS.SETTINGS_VIEW],
|
||||
mutate: [PERMS.SETTINGS_EDIT],
|
||||
},
|
||||
dependencies: {
|
||||
queries: ["WebsiteSetting"],
|
||||
mutations: [
|
||||
"createSetting",
|
||||
"deleteSetting",
|
||||
"saveManagedSettings",
|
||||
"siteSettings.reload",
|
||||
"updateSetting",
|
||||
],
|
||||
},
|
||||
auditRequirement: "PRIVILEGED_MUTATION",
|
||||
localization: "PARTIAL",
|
||||
accessibility: "PARTIAL",
|
||||
notes: [
|
||||
"Global setting changes can also invalidate official gamedata and badge caches",
|
||||
],
|
||||
}),
|
||||
];
|
||||
Reference in new issue
Block a user