docs: audit housekeeping content workflows

This commit is contained in:
Simo committed 2026-08-25 18:14:29 +02:00
1 parent eb9f01d6fe
commit 09850c807c
2 files changed
+668

No files matched your search

@@ -0,0 +1,96 @@
import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import { contentMigrationEntries } from "./content";
import { ownedLegacyPages } from "./discover-legacy-pages";
import { validateMigrationEntries } from "./validate-matrix";
const CONTENT_PREFIXES = [
"/admin/articles",
"/admin/photos",
"/admin/media",
"/admin/banners",
"/admin/ads",
"/admin/events",
"/admin/polls",
"/admin/help-questions",
"/admin/tags",
"/admin/prefixes",
"/admin/writeable-boxes",
"/admin/email-templates",
"/admin/theme",
"/admin/favicon",
"/admin/translations",
] as const;
describe("contentMigrationEntries", () => {
it("covers every content page without legacy-domain targets", () => {
const expected = ownedLegacyPages(CONTENT_PREFIXES);
expect(validateMigrationEntries(expected, contentMigrationEntries)).toEqual(
[],
);
expect(
contentMigrationEntries.every(
(row) =>
row.targetPath === null ||
row.targetPath.startsWith("/admin/content/"),
),
).toBe(true);
});
it("preserves dynamic ids in the consolidated workflow targets", () => {
expect(
contentMigrationEntries
.filter((row) => row.legacyPath.endsWith(":id"))
.map(({ legacyPath, targetPath }) => ({ legacyPath, targetPath })),
).toEqual([
{
legacyPath: "/admin/articles/:id",
targetPath: "/admin/content/editorial/articles/:id",
},
{
legacyPath: "/admin/ads/:id",
targetPath: "/admin/content/media/ads/:id",
},
{
legacyPath: "/admin/events/:id",
targetPath: "/admin/content/engagement/events/:id",
},
{
legacyPath: "/admin/polls/:id",
targetPath: "/admin/content/engagement/polls/:id",
},
{
legacyPath: "/admin/help-questions/:id",
targetPath: "/admin/content/help/questions/:id",
},
]);
});
it("keeps every audited workflow planned without parity claims", () => {
expect(
contentMigrationEntries.every(
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
it("requires privileged settings edits for global runtime configuration", () => {
for (const legacyPath of [
"/admin/theme",
"/admin/favicon",
"/admin/translations/cms",
"/admin/translations/client",
"/admin/translations/emulator",
]) {
expect(contentMigrationEntries).toContainEqual(
expect.objectContaining({
legacyPath,
capabilities: expect.objectContaining({
mutate: [PERMS.SETTINGS_EDIT],
}),
auditRequirement: "PRIVILEGED_MUTATION",
}),
);
}
});
});
@@ -0,0 +1,572 @@
import { PERMS } from "@/lib/permission-slugs";
import type { MigrationEntry } from "./types";
type PlannedContentEntry = Omit<
MigrationEntry,
"targetDomain" | "requiredTests" | "parityEvidence" | "status" | "notes"
> & {
requiredTests?: MigrationEntry["requiredTests"];
notes?: MigrationEntry["notes"];
};
function plannedContentEntry(entry: PlannedContentEntry): MigrationEntry {
return {
...entry,
targetDomain: "content",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
export const contentMigrationEntries: readonly MigrationEntry[] = [
// Batch 1: editorial publishing and media management.
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/articles",
sourceFile: "src/app/admin/articles/page.tsx",
targetPath: "/admin/content/editorial/articles",
decision: "REBUILD",
capabilities: {
read: [PERMS.NEWS_VIEW],
mutate: [PERMS.NEWS_EDIT],
},
dependencies: {
queries: ["User", "WebsiteArticles"],
mutations: ["deleteArticle"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/articles/new",
sourceFile: "src/app/admin/articles/new/page.tsx",
targetPath: "/admin/content/editorial/articles/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.NEWS_EDIT],
mutate: [PERMS.NEWS_EDIT],
},
dependencies: {
queries: ["GET /api/media"],
mutations: ["createArticle", "uploadMediaAndReturn"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/articles/:id",
sourceFile: "src/app/admin/articles/[id]/page.tsx",
targetPath: "/admin/content/editorial/articles/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.NEWS_VIEW],
mutate: [PERMS.NEWS_EDIT],
},
dependencies: {
queries: ["GET /api/media", "WebsiteArticles"],
mutations: ["deleteArticle", "updateArticle", "uploadMediaAndReturn"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/photos",
sourceFile: "src/app/admin/photos/page.tsx",
targetPath: "/admin/content/media/photos",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["CameraWeb", "User"],
mutations: ["deletePhoto"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/media",
sourceFile: "src/app/admin/media/page.tsx",
targetPath: "/admin/content/media/library",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["GET /api/media"],
mutations: ["deleteMedia", "uploadMedia"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/banners",
sourceFile: "src/app/admin/banners/page.tsx",
targetPath: "/admin/content/media/banners",
decision: "REBUILD",
capabilities: {
read: [PERMS.BANNERS_VIEW],
mutate: [PERMS.BANNERS_EDIT],
},
dependencies: {
queries: ["WebsiteBanner"],
mutations: ["createBanner", "deleteBanner", "updateBanner"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/ads",
sourceFile: "src/app/admin/ads/page.tsx",
targetPath: "/admin/content/media/ads",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["WebsiteAds"],
mutations: ["deleteAd"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/ads/new",
sourceFile: "src/app/admin/ads/new/page.tsx",
targetPath: "/admin/content/media/ads/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_EDIT],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: { queries: [], mutations: ["createAd"] },
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/ads/:id",
sourceFile: "src/app/admin/ads/[id]/page.tsx",
targetPath: "/admin/content/media/ads/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["WebsiteAds"],
mutations: ["deleteAd", "updateAd"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
// Batch 2: events, polls, help content, and supporting taxonomies.
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/events",
sourceFile: "src/app/admin/events/page.tsx",
targetPath: "/admin/content/engagement/events",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_VIEW],
mutate: [PERMS.EVENTS_EDIT],
},
dependencies: {
queries: ["fetchAdminList", "WebsiteEvent", "WebsiteEventType"],
mutations: ["deleteEvent"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/events/create",
sourceFile: "src/app/admin/events/create/page.tsx",
targetPath: "/admin/content/engagement/events/create",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_EDIT],
mutate: [PERMS.EVENTS_EDIT],
},
dependencies: {
queries: ["WebsiteEventType"],
mutations: ["createEvent"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/events/types",
sourceFile: "src/app/admin/events/types/page.tsx",
targetPath: "/admin/content/engagement/events/types",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_EDIT],
mutate: [PERMS.EVENTS_EDIT],
},
dependencies: {
queries: ["WebsiteEventType"],
mutations: ["createEventType", "deleteEventType", "updateEventType"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/events/:id",
sourceFile: "src/app/admin/events/[id]/page.tsx",
targetPath: "/admin/content/engagement/events/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_EDIT],
mutate: [PERMS.EVENTS_EDIT],
},
dependencies: {
queries: ["User", "WebsiteEvent", "WebsiteEventType"],
mutations: [
"addEventPrize",
"addEventWinner",
"deleteEventPrize",
"updateEvent",
],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/polls",
sourceFile: "src/app/admin/polls/page.tsx",
targetPath: "/admin/content/engagement/polls",
decision: "REBUILD",
capabilities: {
read: [PERMS.POLLS_VIEW],
mutate: [PERMS.POLLS_EDIT],
},
dependencies: {
queries: ["fetchAdminList", "WebsitePoll"],
mutations: ["deletePoll"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/polls/create",
sourceFile: "src/app/admin/polls/create/page.tsx",
targetPath: "/admin/content/engagement/polls/create",
decision: "REBUILD",
capabilities: {
read: [PERMS.POLLS_EDIT],
mutate: [PERMS.POLLS_EDIT],
},
dependencies: { queries: [], mutations: ["createPoll"] },
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/polls/:id",
sourceFile: "src/app/admin/polls/[id]/page.tsx",
targetPath: "/admin/content/engagement/polls/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.POLLS_EDIT],
mutate: [PERMS.POLLS_EDIT],
},
dependencies: {
queries: ["WebsitePoll"],
mutations: [
"addPollQuestion",
"deletePollQuestion",
"updatePoll",
"updatePollQuestion",
],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/help-questions",
sourceFile: "src/app/admin/help-questions/page.tsx",
targetPath: "/admin/content/help/questions",
decision: "REBUILD",
capabilities: { read: [PERMS.PAGES_VIEW], mutate: [] },
dependencies: {
queries: ["WebsiteHelpCenterCategories"],
mutations: [],
},
auditRequirement: "NONE",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/help-questions/new",
sourceFile: "src/app/admin/help-questions/new/page.tsx",
targetPath: "/admin/content/help/questions/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_EDIT],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: { queries: [], mutations: ["createHelpQuestion"] },
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/help-questions/:id",
sourceFile: "src/app/admin/help-questions/[id]/page.tsx",
targetPath: "/admin/content/help/questions/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["WebsiteHelpCenterCategories"],
mutations: ["deleteHelpQuestion", "updateHelpQuestion"],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/tags",
sourceFile: "src/app/admin/tags/page.tsx",
targetPath: "/admin/content/editorial/tags",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["Taggables", "Tags"],
mutations: ["createTag", "deleteTag", "updateTag"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/prefixes",
sourceFile: "src/app/admin/prefixes/page.tsx",
targetPath: "/admin/content/engagement/prefixes",
decision: "REBUILD",
capabilities: {
read: [PERMS.PREFIXES_VIEW],
mutate: [PERMS.PREFIXES_EDIT],
},
dependencies: {
queries: [
"GET /api/admin/prefixes",
"GET /api/admin/prefixes/blacklist",
"GET /api/admin/prefixes/settings",
],
mutations: [
"addBlacklistWord",
"createPrefix",
"deletePrefix",
"removeBlacklistWord",
"updatePrefix",
"updatePrefixSettings",
],
},
auditRequirement: "MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/writeable-boxes",
sourceFile: "src/app/admin/writeable-boxes/page.tsx",
targetPath: "/admin/content/editorial/writeable-boxes",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["WebsiteWriteableBoxes"],
mutations: ["createBox", "deleteBox", "toggleBox", "updateBox"],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/email-templates",
sourceFile: "src/app/admin/email-templates/page.tsx",
targetPath: "/admin/content/help/email-templates",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
mutate: [PERMS.PAGES_EDIT],
},
dependencies: {
queries: ["EmailTemplates"],
mutations: [
"createEmailTemplate",
"deleteEmailTemplate",
"updateEmailTemplate",
],
},
auditRequirement: "MUTATION",
localization: "COMPLETE",
accessibility: "PARTIAL",
}),
// Batch 3: brand presentation and global localization configuration.
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/theme",
sourceFile: "src/app/admin/theme/page.tsx",
targetPath: "/admin/content/brand/theme",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
mutate: [PERMS.SETTINGS_EDIT],
},
dependencies: {
queries: ["listCustomThemes", "siteSettings.get"],
mutations: [
"applyCustomTheme",
"applyPreset",
"deleteCustomTheme",
"renameCustomTheme",
"saveCustomTheme",
"saveTheme",
],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/favicon",
sourceFile: "src/app/admin/favicon/page.tsx",
targetPath: "/admin/content/brand/favicon",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
mutate: [PERMS.SETTINGS_EDIT],
},
dependencies: {
queries: ["WebsiteSetting"],
mutations: ["deleteFavicon", "saveFavicon"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: [
"Current favicon actions do not enforce an edit permission or emit an audit record",
],
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/translations",
sourceFile: "src/app/admin/translations/page.tsx",
targetPath: "/admin/content/localization",
decision: "MERGE",
capabilities: { read: [PERMS.SETTINGS_VIEW], mutate: [] },
dependencies: { queries: [], mutations: [] },
auditRequirement: "NONE",
localization: "COMPLETE",
accessibility: "COMPLETE",
requiredTests: ["e2e"],
notes: ["Redirect-only landing page for the localization workflow"],
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/translations/client",
sourceFile: "src/app/admin/translations/client/page.tsx",
targetPath: "/admin/content/localization/client",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
mutate: [PERMS.SETTINGS_EDIT],
},
dependencies: {
queries: ["CLIENT_TRANSLATION_FILES", "fs.readFile"],
mutations: ["saveClientTranslations"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Current file mutation does not emit an audit record"],
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/translations/cms",
sourceFile: "src/app/admin/translations/cms/page.tsx",
targetPath: "/admin/content/localization/cms",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
mutate: [PERMS.SETTINGS_EDIT],
},
dependencies: {
queries: ["fs.readFile"],
mutations: ["saveTranslations"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
notes: ["Current file mutation does not emit an audit record"],
}),
plannedContentEntry({
surface: "admin",
legacyPath: "/admin/translations/emulator",
sourceFile: "src/app/admin/translations/emulator/page.tsx",
targetPath: "/admin/content/localization/emulator",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
mutate: [PERMS.SETTINGS_EDIT],
},
dependencies: {
queries: ["EmulatorSettings"],
mutations: ["saveEmulatorSettings"],
},
auditRequirement: "PRIVILEGED_MUTATION",
localization: "PARTIAL",
accessibility: "PARTIAL",
}),
];