From eb9f01d6fe72f9373ce045dbd4f80aa0ed3017f9 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 24 Aug 2026 21:38:30 +0200 Subject: [PATCH] docs: audit housekeeping people workflows --- .../housekeeping/migration/operations.test.ts | 36 + .../housekeeping/migration/operations.ts | 27 + .../housekeeping/migration/people.test.ts | 70 ++ src/features/housekeeping/migration/people.ts | 835 ++++++++++++++++++ 4 files changed, 968 insertions(+) create mode 100644 src/features/housekeeping/migration/operations.test.ts create mode 100644 src/features/housekeeping/migration/operations.ts create mode 100644 src/features/housekeeping/migration/people.test.ts create mode 100644 src/features/housekeeping/migration/people.ts diff --git a/src/features/housekeeping/migration/operations.test.ts b/src/features/housekeeping/migration/operations.test.ts new file mode 100644 index 00000000..a50c8cd3 --- /dev/null +++ b/src/features/housekeeping/migration/operations.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from "vitest"; +import { PERMS } from "@/lib/permission-slugs"; +import { operationsMigrationEntries } from "./operations"; + +describe("operationsMigrationEntries", () => { + it("covers the legacy dashboard once", () => { + expect(operationsMigrationEntries).toHaveLength(1); + expect(operationsMigrationEntries[0]).toMatchObject({ + surface: "admin", + legacyPath: "/admin", + sourceFile: "src/app/admin/page.tsx", + targetDomain: "operations", + targetPath: "/admin/work", + decision: "REBUILD", + capabilities: { read: [PERMS.ADMIN_DASHBOARD], mutate: [] }, + dependencies: { + queries: [ + "users", + "active bans", + "website articles", + "staff activities", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + requiredTests: ["integration", "e2e", "visual"], + parityEvidence: [], + status: "PLANNED", + notes: [ + "Replace metric dashboard with capability-derived operational home", + ], + }); + }); +}); diff --git a/src/features/housekeeping/migration/operations.ts b/src/features/housekeeping/migration/operations.ts new file mode 100644 index 00000000..9188e7af --- /dev/null +++ b/src/features/housekeeping/migration/operations.ts @@ -0,0 +1,27 @@ +import { PERMS } from "@/lib/permission-slugs"; +import type { MigrationEntry } from "./types"; + +export const operationsMigrationEntries: readonly MigrationEntry[] = [ + { + surface: "admin", + legacyPath: "/admin", + sourceFile: "src/app/admin/page.tsx", + targetDomain: "operations", + targetPath: "/admin/work", + decision: "REBUILD", + capabilities: { read: [PERMS.ADMIN_DASHBOARD], mutate: [] }, + dependencies: { + queries: ["users", "active bans", "website articles", "staff activities"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + requiredTests: ["integration", "e2e", "visual"], + parityEvidence: [], + status: "PLANNED", + notes: [ + "Replace metric dashboard with capability-derived operational home", + ], + }, +]; diff --git a/src/features/housekeeping/migration/people.test.ts b/src/features/housekeeping/migration/people.test.ts new file mode 100644 index 00000000..a6950113 --- /dev/null +++ b/src/features/housekeeping/migration/people.test.ts @@ -0,0 +1,70 @@ +import { describe, expect, it } from "vitest"; +import { discoverLegacyPages } from "./discover-legacy-pages"; +import { operationsMigrationEntries } from "./operations"; +import { peopleMigrationEntries } from "./people"; +import { validateMigrationEntries } from "./validate-matrix"; + +const PEOPLE_PREFIXES = [ + "/admin/users", + "/admin/online", + "/admin/guilds", + "/admin/applications", + "/admin/teams", + "/admin/bans", + "/admin/ip", + "/admin/vpn", + "/admin/wordfilter", + "/admin/moderation", + "/admin/tickets", + "/admin/help-tickets", + "/mod", +] as const; + +describe("peopleMigrationEntries", () => { + it("merges every mod page into a people workflow", () => { + const modRows = peopleMigrationEntries.filter( + (row) => row.surface === "mod", + ); + + expect(modRows).toHaveLength(13); + expect(modRows.every((row) => row.decision === "MERGE")).toBe(true); + expect( + modRows.every((row) => row.targetPath?.startsWith("/admin/people/")), + ).toBe(true); + }); + + it("merges duplicate user detail and edit aliases", () => { + for (const legacyPath of ["/admin/users/:id", "/admin/users/:id/edit"]) { + expect(peopleMigrationEntries).toContainEqual( + expect.objectContaining({ legacyPath, decision: "MERGE" }), + ); + } + }); + + it("keeps planned rows free of unverified parity claims", () => { + expect( + peopleMigrationEntries.every( + (row) => row.status === "PLANNED" && row.parityEvidence.length === 0, + ), + ).toBe(true); + }); + + it("covers every Operations and People legacy page exactly once", () => { + const expected = discoverLegacyPages().filter( + (page) => + page.legacyPath === "/admin" || + PEOPLE_PREFIXES.some( + (prefix) => + page.legacyPath === prefix || + page.legacyPath.startsWith(`${prefix}/`), + ), + ); + + expect( + validateMigrationEntries(expected, [ + ...operationsMigrationEntries, + ...peopleMigrationEntries, + ]), + ).toEqual([]); + }); +}); diff --git a/src/features/housekeeping/migration/people.ts b/src/features/housekeeping/migration/people.ts new file mode 100644 index 00000000..54e326cf --- /dev/null +++ b/src/features/housekeeping/migration/people.ts @@ -0,0 +1,835 @@ +import { PERMS } from "@/lib/permission-slugs"; +import type { MigrationEntry } from "./types"; + +type PlannedPeopleEntry = Omit< + MigrationEntry, + "targetDomain" | "requiredTests" | "parityEvidence" | "status" | "notes" +> & { + requiredTests?: MigrationEntry["requiredTests"]; + notes?: MigrationEntry["notes"]; +}; + +function plannedPeopleEntry(entry: PlannedPeopleEntry): MigrationEntry { + return { + ...entry, + targetDomain: "people", + requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"], + parityEvidence: [], + status: "PLANNED", + notes: entry.notes ?? [], + }; +} + +export const peopleMigrationEntries: readonly MigrationEntry[] = [ + // Batch 1: users, aliases, online users, guilds, and applications. + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/users", + sourceFile: "src/app/admin/users/page.tsx", + targetPath: "/admin/people/users", + decision: "REBUILD", + capabilities: { + read: [PERMS.USERS_VIEW], + mutate: [PERMS.USERS_EDIT, PERMS.USERS_BAN], + }, + dependencies: { + queries: ["fetchAdminList", "User"], + mutations: [ + "createUser", + "bulkAdjustCurrency", + "bulkBan", + "bulkGiveBadge", + "bulkUnban", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/users/edit/:id", + sourceFile: "src/app/admin/users/edit/[id]/page.tsx", + targetPath: "/admin/people/users/:id/edit", + decision: "REBUILD", + capabilities: { + read: [PERMS.USERS_EDIT], + mutate: [PERMS.USERS_EDIT, PERMS.USERS_BAN, PERMS.USERS_RESET_PASSWORD], + }, + dependencies: { + queries: ["loadUserById", "getWatchedUserIds", "permissions"], + mutations: [ + "updateUser", + "giveBadge", + "removeBadge", + "banUser", + "unbanUser", + "alertUser", + "disconnectUser", + "muteUser", + "unmuteUser", + "resetPassword", + "sendCredits", + "setTradeLock", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/users/multi-accounts", + sourceFile: "src/app/admin/users/multi-accounts/page.tsx", + targetPath: "/admin/people/users/multi-accounts", + decision: "REBUILD", + capabilities: { read: [PERMS.USERS_VIEW], mutate: [] }, + dependencies: { queries: ["detectMultiAccounts"], mutations: [] }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/users/show/:id", + sourceFile: "src/app/admin/users/show/[id]/page.tsx", + targetPath: "/admin/people/users/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.USERS_VIEW], + mutate: [PERMS.USERS_EDIT, PERMS.USERS_BAN, PERMS.USERS_RESET_PASSWORD], + }, + dependencies: { + queries: ["loadUserById", "loadUserSanctions", "getWatchedUserIds"], + mutations: [ + "alertUser", + "disconnectUser", + "muteUser", + "unmuteUser", + "resetPassword", + "sendCredits", + "setTradeLock", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/users/:id", + sourceFile: "src/app/admin/users/[id]/page.tsx", + targetPath: "/admin/people/users/:id", + decision: "MERGE", + capabilities: { read: [PERMS.USERS_VIEW], mutate: [] }, + dependencies: { queries: [], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "COMPLETE", + requiredTests: ["e2e"], + notes: ["Redirect-only duplicate of the canonical user detail route"], + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/users/:id/edit", + sourceFile: "src/app/admin/users/[id]/edit/page.tsx", + targetPath: "/admin/people/users/:id/edit", + decision: "MERGE", + capabilities: { read: [PERMS.USERS_EDIT], mutate: [] }, + dependencies: { queries: [], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "COMPLETE", + requiredTests: ["e2e"], + notes: ["Redirect-only duplicate of the canonical user edit route"], + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/online", + sourceFile: "src/app/admin/online/page.tsx", + targetPath: "/admin/people/community/online", + decision: "REBUILD", + capabilities: { read: [PERMS.USERS_VIEW], mutate: [] }, + dependencies: { queries: ["fetchAdminList", "User"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/guilds", + sourceFile: "src/app/admin/guilds/page.tsx", + targetPath: "/admin/people/community/guilds", + decision: "REBUILD", + capabilities: { read: [PERMS.USERS_VIEW], mutate: [] }, + dependencies: { + queries: ["Guilds", "GuildsMembers", "User"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/guilds/:id", + sourceFile: "src/app/admin/guilds/[id]/page.tsx", + targetPath: "/admin/people/community/guilds/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.USERS_VIEW], + mutate: [PERMS.USERS_EDIT], + }, + dependencies: { + queries: ["Guilds", "GuildsForumsThreads", "GuildsMembers", "User"], + mutations: ["disbandGuild"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/applications", + sourceFile: "src/app/admin/applications/page.tsx", + targetPath: "/admin/people/staff/applications", + decision: "REBUILD", + capabilities: { + read: [PERMS.USERS_VIEW], + mutate: [PERMS.USERS_EDIT], + }, + dependencies: { + queries: ["WebsiteStaffApplications", "User"], + mutations: ["dismissApplication"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + + // Batch 2: staff, moderation, CFH, bans, IP, VPN, and word filter. + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/teams", + sourceFile: "src/app/admin/teams/page.tsx", + targetPath: "/admin/people/staff/teams", + decision: "REBUILD", + capabilities: { + read: [PERMS.USERS_VIEW], + mutate: [PERMS.USERS_EDIT], + }, + dependencies: { + queries: ["WebsiteTeams"], + mutations: ["createTeam", "deleteTeam"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/moderation", + sourceFile: "src/app/admin/moderation/page.tsx", + targetPath: "/admin/people/moderation", + decision: "REBUILD", + capabilities: { read: [PERMS.MODERATION_VIEW], mutate: [] }, + dependencies: { + queries: [ + "getMinStaffRank", + "AdminAuditLog", + "Ban", + "SupportTickets", + "User", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/moderation/actions", + sourceFile: "src/app/admin/moderation/actions/page.tsx", + targetPath: "/admin/people/moderation/actions", + decision: "REBUILD", + capabilities: { + read: [PERMS.MODERATION_EDIT], + mutate: [PERMS.MODERATION_EDIT], + }, + dependencies: { + queries: [], + mutations: [ + "broadcastAlert", + "quickAlert", + "quickKick", + "quickMute", + "quickRoomKick", + "quickUnmute", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/moderation/cfh", + sourceFile: "src/app/admin/moderation/cfh/page.tsx", + targetPath: "/admin/people/moderation/cfh", + decision: "REBUILD", + capabilities: { read: [PERMS.MODERATION_VIEW], mutate: [] }, + dependencies: { queries: ["SupportTickets", "User"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/moderation/cfh/:id", + sourceFile: "src/app/admin/moderation/cfh/[id]/page.tsx", + targetPath: "/admin/people/moderation/cfh/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.MODERATION_VIEW], + mutate: [PERMS.MODERATION_EDIT], + }, + dependencies: { + queries: ["Ban", "SupportTickets", "User"], + mutations: [ + "assignCfhTicket", + "closeCfhTicket", + "quickAlert", + "quickKick", + "quickMute", + "updateCfhState", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/moderation/team", + sourceFile: "src/app/admin/moderation/team/page.tsx", + targetPath: "/admin/people/staff/moderation-team", + decision: "REBUILD", + capabilities: { read: [PERMS.MODERATION_VIEW], mutate: [] }, + dependencies: { + queries: [ + "getMinStaffRank", + "AdminAuditLog", + "SupportTickets", + "User", + "WebsiteTicket", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/bans", + sourceFile: "src/app/admin/bans/page.tsx", + targetPath: "/admin/people/moderation/bans", + decision: "REBUILD", + capabilities: { + read: [PERMS.BANS_VIEW], + mutate: [PERMS.USERS_BAN], + }, + dependencies: { + queries: ["Ban"], + mutations: ["createBan", "liftBan"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/ip", + sourceFile: "src/app/admin/ip/page.tsx", + targetPath: "/admin/people/moderation/ip", + decision: "REBUILD", + capabilities: { + read: [PERMS.SETTINGS_VIEW], + mutate: [PERMS.SETTINGS_EDIT], + }, + dependencies: { + queries: ["WebsiteIpBlacklist", "WebsiteIpWhitelist"], + mutations: [ + "addBlacklist", + "addWhitelist", + "deleteBlacklist", + "deleteWhitelist", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/vpn", + sourceFile: "src/app/admin/vpn/page.tsx", + targetPath: "/admin/people/moderation/vpn", + decision: "REBUILD", + capabilities: { + read: [PERMS.SETTINGS_VIEW], + mutate: [PERMS.SETTINGS_EDIT], + }, + dependencies: { + queries: ["siteSettings.getMany"], + mutations: ["saveVpn"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/wordfilter", + sourceFile: "src/app/admin/wordfilter/page.tsx", + targetPath: "/admin/people/moderation/word-filter", + decision: "REBUILD", + capabilities: { + read: [PERMS.WORDFILTER_VIEW], + mutate: [PERMS.WORDFILTER_EDIT], + }, + dependencies: { + queries: ["WebsiteWordfilter"], + mutations: ["addWord", "deleteWord"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + + // Batch 3: website tickets and help-center tickets. + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/tickets", + sourceFile: "src/app/admin/tickets/page.tsx", + targetPath: "/admin/people/support/tickets", + decision: "REBUILD", + capabilities: { read: [PERMS.TICKETS_VIEW], mutate: [] }, + dependencies: { + queries: ["fetchUnifiedTicketInbox", "fetchTicketQueueOpenCounts"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/tickets/desk", + sourceFile: "src/app/admin/tickets/desk/page.tsx", + targetPath: "/admin/people/support/tickets/desk", + decision: "REBUILD", + capabilities: { read: [PERMS.TICKETS_VIEW], mutate: [] }, + dependencies: { + queries: ["fetchTicketQueueOpenCounts", "User", "WebsiteTicket"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/tickets/templates", + sourceFile: "src/app/admin/tickets/templates/page.tsx", + targetPath: "/admin/people/support/tickets/templates", + decision: "REBUILD", + capabilities: { + read: [PERMS.TICKETS_EDIT], + mutate: [PERMS.TICKETS_EDIT], + }, + dependencies: { + queries: ["WebsiteTicketTemplate"], + mutations: ["createTemplate", "deleteTemplate", "updateTemplate"], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/tickets/:id", + sourceFile: "src/app/admin/tickets/[id]/page.tsx", + targetPath: "/admin/people/support/tickets/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.TICKETS_VIEW], + mutate: [PERMS.TICKETS_EDIT], + }, + dependencies: { + queries: [ + "getMinStaffRank", + "fetchTicketQueueOpenCounts", + "User", + "WebsiteTicket", + ], + mutations: [ + "adminReplyTicket", + "assignTicket", + "updateTicketPriority", + "updateTicketStatus", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/help-tickets", + sourceFile: "src/app/admin/help-tickets/page.tsx", + targetPath: "/admin/people/support/help-tickets", + decision: "REBUILD", + capabilities: { read: [PERMS.TICKETS_VIEW], mutate: [] }, + dependencies: { + queries: [ + "fetchTicketQueueOpenCounts", + "User", + "WebsiteHelpCenterTicketReplies", + "WebsiteHelpCenterTickets", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "admin", + legacyPath: "/admin/help-tickets/:id", + sourceFile: "src/app/admin/help-tickets/[id]/page.tsx", + targetPath: "/admin/people/support/help-tickets/:id", + decision: "REBUILD", + capabilities: { + read: [PERMS.TICKETS_VIEW], + mutate: [PERMS.TICKETS_EDIT, PERMS.USERS_BAN], + }, + dependencies: { + queries: [ + "getMinStaffRank", + "fetchTicketQueueOpenCounts", + "Ban", + "User", + "WebsiteHelpCenterCategories", + "WebsiteHelpCenterTicketReplies", + "WebsiteHelpCenterTickets", + ], + mutations: [ + "closeHelpCenterTicket", + "liftBanFromHelpTicket", + "reopenHelpCenterTicket", + "replyHelpCenterTicket", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + + // Batch 4: merge all moderator routes into the People workflows. + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod", + sourceFile: "src/app/mod/page.tsx", + targetPath: "/admin/people/moderation", + decision: "MERGE", + capabilities: { + read: [ + PERMS.MOD_CFH_VIEW, + PERMS.MODERATION_VIEW, + PERMS.MOD_ACTIONS, + PERMS.MODERATION_EDIT, + PERMS.MOD_BANS_VIEW, + PERMS.BANS_VIEW, + PERMS.MOD_TICKETS_VIEW, + PERMS.TICKETS_VIEW, + PERMS.MOD_TEAM_VIEW, + PERMS.MOD_USERS_VIEW, + PERMS.USERS_VIEW, + ], + mutate: [], + }, + dependencies: { + queries: [ + "getMinStaffRank", + "Ban", + "SupportTickets", + "User", + "WebsiteHelpCenterTickets", + "WebsiteTicket", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + notes: ["Merge the moderator dashboard into capability-gated People work"], + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/actions", + sourceFile: "src/app/mod/actions/page.tsx", + targetPath: "/admin/people/moderation/actions", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_ACTIONS, PERMS.MODERATION_EDIT], + mutate: [PERMS.MOD_ACTIONS, PERMS.MODERATION_EDIT], + }, + dependencies: { + queries: [], + mutations: [ + "broadcastAlert", + "quickAlert", + "quickKick", + "quickMute", + "quickRoomKick", + "quickUnmute", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/bans", + sourceFile: "src/app/mod/bans/page.tsx", + targetPath: "/admin/people/moderation/bans", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_BANS_VIEW, PERMS.BANS_VIEW], + mutate: [], + }, + dependencies: { queries: ["Ban"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/cfh", + sourceFile: "src/app/mod/cfh/page.tsx", + targetPath: "/admin/people/moderation/cfh", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_CFH_VIEW, PERMS.MODERATION_VIEW], + mutate: [], + }, + dependencies: { queries: ["SupportTickets", "User"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/cfh/:id", + sourceFile: "src/app/mod/cfh/[id]/page.tsx", + targetPath: "/admin/people/moderation/cfh/:id", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_CFH_VIEW, PERMS.MODERATION_VIEW], + mutate: [PERMS.MOD_CFH_EDIT, PERMS.MODERATION_EDIT], + }, + dependencies: { + queries: ["Ban", "SupportTickets", "User"], + mutations: [ + "assignCfhTicket", + "closeCfhTicket", + "quickAlert", + "quickKick", + "quickMute", + "updateCfhState", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/help-tickets", + sourceFile: "src/app/mod/help-tickets/page.tsx", + targetPath: "/admin/people/support/help-tickets", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW], + mutate: [], + }, + dependencies: { + queries: [ + "fetchTicketQueueOpenCounts", + "User", + "WebsiteHelpCenterTicketReplies", + "WebsiteHelpCenterTickets", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/help-tickets/:id", + sourceFile: "src/app/mod/help-tickets/[id]/page.tsx", + targetPath: "/admin/people/support/help-tickets/:id", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW], + mutate: [PERMS.MOD_TICKETS_EDIT, PERMS.TICKETS_EDIT, PERMS.USERS_BAN], + }, + dependencies: { + queries: [ + "getMinStaffRank", + "fetchTicketQueueOpenCounts", + "User", + "WebsiteHelpCenterTicketReplies", + "WebsiteHelpCenterTickets", + ], + mutations: [ + "closeHelpCenterTicket", + "liftBanFromHelpTicket", + "reopenHelpCenterTicket", + "replyHelpCenterTicket", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/team", + sourceFile: "src/app/mod/team/page.tsx", + targetPath: "/admin/people/staff/moderation-team", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_TEAM_VIEW, PERMS.MODERATION_VIEW], + mutate: [], + }, + dependencies: { + queries: [ + "getMinStaffRank", + "AdminAuditLog", + "SupportTickets", + "User", + "WebsiteTicket", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "PARTIAL", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/tickets", + sourceFile: "src/app/mod/tickets/page.tsx", + targetPath: "/admin/people/support/tickets", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW], + mutate: [], + }, + dependencies: { + queries: ["fetchUnifiedTicketInbox", "fetchTicketQueueOpenCounts"], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/tickets/desk", + sourceFile: "src/app/mod/tickets/desk/page.tsx", + targetPath: "/admin/people/support/tickets/desk", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW], + mutate: [], + }, + dependencies: { + queries: [ + "fetchTicketQueueOpenCounts", + "User", + "WebsiteTicket", + "WebsiteTicketMessage", + ], + mutations: [], + }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/tickets/:id", + sourceFile: "src/app/mod/tickets/[id]/page.tsx", + targetPath: "/admin/people/support/tickets/:id", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW], + mutate: [PERMS.MOD_TICKETS_EDIT, PERMS.TICKETS_EDIT], + }, + dependencies: { + queries: [ + "getMinStaffRank", + "fetchTicketQueueOpenCounts", + "User", + "WebsiteTicket", + "WebsiteTicketMessage", + ], + mutations: [ + "adminReplyTicket", + "assignTicket", + "updateTicketPriority", + "updateTicketStatus", + ], + }, + auditRequirement: "PRIVILEGED_MUTATION", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/users", + sourceFile: "src/app/mod/users/page.tsx", + targetPath: "/admin/people/users", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_USERS_VIEW, PERMS.USERS_VIEW], + mutate: [], + }, + dependencies: { queries: ["User"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), + plannedPeopleEntry({ + surface: "mod", + legacyPath: "/mod/users/:id", + sourceFile: "src/app/mod/users/[id]/page.tsx", + targetPath: "/admin/people/users/:id", + decision: "MERGE", + capabilities: { + read: [PERMS.MOD_USERS_VIEW, PERMS.USERS_VIEW], + mutate: [], + }, + dependencies: { queries: ["User"], mutations: [] }, + auditRequirement: "NONE", + localization: "COMPLETE", + accessibility: "PARTIAL", + }), +];