Revert "Merge pull request 'Complete Housekeeping migration and /ase cutover' (#52) from codex/housekeeping-complete into main"
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 43s

This reverts commit 488b6e57c4, reversing
changes made to b506b4499a.
This commit is contained in:
Simo committed 2026-08-30 21:31:34 +02:00
1 parent 488b6e57c4
commit b1ddda66ff
802 files changed
+61370 -76659

No files matched your search

@@ -1,8 +1,7 @@
import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import { contentMigrationEntries } from "./content";
import { ownedLegacyPages, recordedLegacyPages } from "./discover-legacy-pages";
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
import { ownedLegacyPages } from "./discover-legacy-pages";
import { validateMigrationEntries } from "./validate-matrix";
const CONTENT_PREFIXES = [
@@ -25,17 +24,15 @@ const CONTENT_PREFIXES = [
describe("contentMigrationEntries", () => {
it("covers every content page without legacy-domain targets", () => {
const expected = ownedLegacyPages(
CONTENT_PREFIXES,
recordedLegacyPages(HOUSEKEEPING_MIGRATION_MATRIX),
);
const expected = ownedLegacyPages(CONTENT_PREFIXES);
expect(validateMigrationEntries(expected, contentMigrationEntries)).toEqual(
[],
);
expect(
contentMigrationEntries.every(
(row) =>
row.targetPath === null || row.targetPath.startsWith("/ase/content/"),
row.targetPath === null ||
row.targetPath.startsWith("/admin/content/"),
),
).toBe(true);
});
@@ -48,33 +45,31 @@ describe("contentMigrationEntries", () => {
).toEqual([
{
legacyPath: "/admin/articles/:id",
targetPath: "/ase/content/editorial/articles/:id",
targetPath: "/admin/content/editorial/articles/:id",
},
{
legacyPath: "/admin/ads/:id",
targetPath: "/ase/content/media/ads/:id",
targetPath: "/admin/content/media/ads/:id",
},
{
legacyPath: "/admin/events/:id",
targetPath: "/ase/content/engagement/events/:id",
targetPath: "/admin/content/engagement/events/:id",
},
{
legacyPath: "/admin/polls/:id",
targetPath: "/ase/content/engagement/polls/:id",
targetPath: "/admin/content/engagement/polls/:id",
},
{
legacyPath: "/admin/help-questions/:id",
targetPath: "/ase/content/help/questions/:id",
targetPath: "/admin/content/help/questions/:id",
},
]);
});
it("records concrete runtime parity evidence for every verified workflow", () => {
it("keeps every audited workflow planned without parity claims", () => {
expect(
contentMigrationEntries.every(
(row) =>
row.status === "VERIFIED" &&
row.parityEvidence.includes(`runtime-parity:${row.legacyPath}`),
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
+31 -31
View File
@@ -14,8 +14,8 @@ function plannedContentEntry(entry: PlannedContentEntry): MigrationEntry {
...entry,
targetDomain: "content",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [`runtime-parity:${entry.legacyPath}`],
status: entry.decision === "REMOVE" ? "REMOVED" : "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
@@ -26,7 +26,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/articles",
sourceFile: "src/app/admin/articles/page.tsx",
targetPath: "/ase/content/editorial/articles",
targetPath: "/admin/content/editorial/articles",
decision: "REBUILD",
capabilities: {
read: [PERMS.NEWS_VIEW],
@@ -44,7 +44,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/articles/new",
sourceFile: "src/app/admin/articles/new/page.tsx",
targetPath: "/ase/content/editorial/articles/new",
targetPath: "/admin/content/editorial/articles/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.NEWS_EDIT],
@@ -62,7 +62,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/articles/:id",
sourceFile: "src/app/admin/articles/[id]/page.tsx",
targetPath: "/ase/content/editorial/articles/:id",
targetPath: "/admin/content/editorial/articles/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.NEWS_VIEW],
@@ -80,7 +80,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/photos",
sourceFile: "src/app/admin/photos/page.tsx",
targetPath: "/ase/content/media/photos",
targetPath: "/admin/content/media/photos",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -98,7 +98,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/media",
sourceFile: "src/app/admin/media/page.tsx",
targetPath: "/ase/content/media/library",
targetPath: "/admin/content/media/library",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -116,7 +116,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/banners",
sourceFile: "src/app/admin/banners/page.tsx",
targetPath: "/ase/content/media/banners",
targetPath: "/admin/content/media/banners",
decision: "REBUILD",
capabilities: {
read: [PERMS.BANNERS_VIEW],
@@ -134,7 +134,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/ads",
sourceFile: "src/app/admin/ads/page.tsx",
targetPath: "/ase/content/media/ads",
targetPath: "/admin/content/media/ads",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -152,7 +152,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/ads/new",
sourceFile: "src/app/admin/ads/new/page.tsx",
targetPath: "/ase/content/media/ads/new",
targetPath: "/admin/content/media/ads/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_EDIT],
@@ -167,7 +167,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/ads/:id",
sourceFile: "src/app/admin/ads/[id]/page.tsx",
targetPath: "/ase/content/media/ads/:id",
targetPath: "/admin/content/media/ads/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -187,7 +187,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/events",
sourceFile: "src/app/admin/events/page.tsx",
targetPath: "/ase/content/engagement/events",
targetPath: "/admin/content/engagement/events",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_VIEW],
@@ -205,7 +205,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/events/create",
sourceFile: "src/app/admin/events/create/page.tsx",
targetPath: "/ase/content/engagement/events/create",
targetPath: "/admin/content/engagement/events/create",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_EDIT],
@@ -223,7 +223,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/events/types",
sourceFile: "src/app/admin/events/types/page.tsx",
targetPath: "/ase/content/engagement/events/types",
targetPath: "/admin/content/engagement/events/types",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_EDIT],
@@ -241,7 +241,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/events/:id",
sourceFile: "src/app/admin/events/[id]/page.tsx",
targetPath: "/ase/content/engagement/events/:id",
targetPath: "/admin/content/engagement/events/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.EVENTS_EDIT],
@@ -264,7 +264,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/polls",
sourceFile: "src/app/admin/polls/page.tsx",
targetPath: "/ase/content/engagement/polls",
targetPath: "/admin/content/engagement/polls",
decision: "REBUILD",
capabilities: {
read: [PERMS.POLLS_VIEW],
@@ -282,7 +282,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/polls/create",
sourceFile: "src/app/admin/polls/create/page.tsx",
targetPath: "/ase/content/engagement/polls/create",
targetPath: "/admin/content/engagement/polls/create",
decision: "REBUILD",
capabilities: {
read: [PERMS.POLLS_EDIT],
@@ -297,7 +297,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/polls/:id",
sourceFile: "src/app/admin/polls/[id]/page.tsx",
targetPath: "/ase/content/engagement/polls/:id",
targetPath: "/admin/content/engagement/polls/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.POLLS_EDIT],
@@ -320,7 +320,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/help-questions",
sourceFile: "src/app/admin/help-questions/page.tsx",
targetPath: "/ase/content/help/questions",
targetPath: "/admin/content/help/questions",
decision: "REBUILD",
capabilities: { read: [PERMS.PAGES_VIEW], mutate: [] },
dependencies: {
@@ -335,7 +335,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/help-questions/new",
sourceFile: "src/app/admin/help-questions/new/page.tsx",
targetPath: "/ase/content/help/questions/new",
targetPath: "/admin/content/help/questions/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_EDIT],
@@ -350,7 +350,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/help-questions/:id",
sourceFile: "src/app/admin/help-questions/[id]/page.tsx",
targetPath: "/ase/content/help/questions/:id",
targetPath: "/admin/content/help/questions/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -368,7 +368,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/tags",
sourceFile: "src/app/admin/tags/page.tsx",
targetPath: "/ase/content/editorial/tags",
targetPath: "/admin/content/editorial/tags",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -386,7 +386,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/prefixes",
sourceFile: "src/app/admin/prefixes/page.tsx",
targetPath: "/ase/content/engagement/prefixes",
targetPath: "/admin/content/engagement/prefixes",
decision: "REBUILD",
capabilities: {
read: [PERMS.PREFIXES_VIEW],
@@ -415,7 +415,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/writeable-boxes",
sourceFile: "src/app/admin/writeable-boxes/page.tsx",
targetPath: "/ase/content/editorial/writeable-boxes",
targetPath: "/admin/content/editorial/writeable-boxes",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -433,7 +433,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/email-templates",
sourceFile: "src/app/admin/email-templates/page.tsx",
targetPath: "/ase/content/help/email-templates",
targetPath: "/admin/content/help/email-templates",
decision: "REBUILD",
capabilities: {
read: [PERMS.PAGES_VIEW],
@@ -457,7 +457,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/theme",
sourceFile: "src/app/admin/theme/page.tsx",
targetPath: "/ase/content/brand/theme",
targetPath: "/admin/content/brand/theme",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -482,7 +482,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/favicon",
sourceFile: "src/app/admin/favicon/page.tsx",
targetPath: "/ase/content/brand/favicon",
targetPath: "/admin/content/brand/favicon",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -503,7 +503,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/translations",
sourceFile: "src/app/admin/translations/page.tsx",
targetPath: "/ase/content/localization",
targetPath: "/admin/content/localization",
decision: "MERGE",
capabilities: { read: [PERMS.SETTINGS_VIEW], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -517,7 +517,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/translations/client",
sourceFile: "src/app/admin/translations/client/page.tsx",
targetPath: "/ase/content/localization/client",
targetPath: "/admin/content/localization/client",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -536,7 +536,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/translations/cms",
sourceFile: "src/app/admin/translations/cms/page.tsx",
targetPath: "/ase/content/localization/cms",
targetPath: "/admin/content/localization/cms",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -555,7 +555,7 @@ export const contentMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/translations/emulator",
sourceFile: "src/app/admin/translations/emulator/page.tsx",
targetPath: "/ase/content/localization/emulator",
targetPath: "/admin/content/localization/emulator",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -26,8 +26,37 @@ function createRouteTree(files: readonly string[]): string {
}
describe("discoverLegacyPages", () => {
it("returns no routes after the atomic cutover", () => {
expect(discoverLegacyPages()).toEqual([]);
it("discovers the exact legacy administration inventory", () => {
const pages = discoverLegacyPages();
expect(pages).toHaveLength(137);
expect(pages).toContainEqual({
surface: "admin",
legacyPath: "/admin/users/:id/edit",
sourceFile: "src/app/admin/users/[id]/edit/page.tsx",
});
expect(pages).toContainEqual({
surface: "mod",
legacyPath: "/mod/cfh/:id",
sourceFile: "src/app/mod/cfh/[id]/page.tsx",
});
});
it("discovers root administration and moderation routes", () => {
expect(discoverLegacyPages()).toEqual(
expect.arrayContaining([
{
surface: "admin",
legacyPath: "/admin",
sourceFile: "src/app/admin/page.tsx",
},
{
surface: "mod",
legacyPath: "/mod",
sourceFile: "src/app/mod/page.tsx",
},
]),
);
});
it("discovers root routes in a controlled route tree", () => {
@@ -1,4 +1,4 @@
import { existsSync, readdirSync } from "node:fs";
import { readdirSync } from "node:fs";
import { join, relative } from "node:path";
import type { LegacyPage, LegacySurface } from "./types";
@@ -23,7 +23,6 @@ function discoverSurface(
): LegacyPage[] {
const surfaceDirectory = join(rootDir, "src", "app", surface);
const pages: LegacyPage[] = [];
if (!existsSync(surfaceDirectory)) return pages;
function walk(directory: string): void {
for (const entry of readdirSync(directory, { withFileTypes: true })) {
@@ -52,22 +51,6 @@ function discoverSurface(
return pages;
}
export function recordedLegacyPages(
entries: readonly LegacyPage[],
): LegacyPage[] {
return entries
.map(({ surface, legacyPath, sourceFile }) => ({
surface,
legacyPath,
sourceFile,
}))
.sort((a, b) =>
`${a.surface}:${a.legacyPath}:${a.sourceFile}`.localeCompare(
`${b.surface}:${b.legacyPath}:${b.sourceFile}`,
),
);
}
export function discoverLegacyPages(rootDir = process.cwd()): LegacyPage[] {
return (["admin", "mod"] as const)
.flatMap((surface) => discoverSurface(rootDir, surface))
@@ -1,7 +1,6 @@
import { describe, expect, it } from "vitest";
import { ownedLegacyPages, recordedLegacyPages } from "./discover-legacy-pages";
import { ownedLegacyPages } from "./discover-legacy-pages";
import { economyMigrationEntries } from "./economy";
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
import { validateMigrationEntries } from "./validate-matrix";
const ECONOMY_PREFIXES = [
@@ -21,27 +20,23 @@ const ECONOMY_PREFIXES = [
describe("economyMigrationEntries", () => {
it("covers every economy page without legacy-domain targets", () => {
const expected = ownedLegacyPages(
ECONOMY_PREFIXES,
recordedLegacyPages(HOUSEKEEPING_MIGRATION_MATRIX),
);
const expected = ownedLegacyPages(ECONOMY_PREFIXES);
expect(validateMigrationEntries(expected, economyMigrationEntries)).toEqual(
[],
);
expect(
economyMigrationEntries.every(
(row) =>
row.targetPath === null || row.targetPath.startsWith("/ase/economy/"),
row.targetPath === null ||
row.targetPath.startsWith("/admin/economy/"),
),
).toBe(true);
});
it("records concrete runtime parity evidence for every verified workflow", () => {
it("keeps every audited workflow planned without parity claims", () => {
expect(
economyMigrationEntries.every(
(row) =>
row.status === "VERIFIED" &&
row.parityEvidence.includes(`runtime-parity:${row.legacyPath}`),
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
+22 -22
View File
@@ -14,8 +14,8 @@ function plannedEconomyEntry(entry: PlannedEconomyEntry): MigrationEntry {
...entry,
targetDomain: "economy",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [`runtime-parity:${entry.legacyPath}`],
status: entry.decision === "REMOVE" ? "REMOVED" : "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
@@ -26,7 +26,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/catalog",
sourceFile: "src/app/admin/catalog/page.tsx",
targetPath: "/ase/economy/catalog",
targetPath: "/admin/economy/catalog",
decision: "MERGE",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -71,7 +71,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/catalog/:id",
sourceFile: "src/app/admin/catalog/[id]/page.tsx",
targetPath: "/ase/economy/catalog/:id",
targetPath: "/admin/economy/catalog/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -108,7 +108,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/catalog/builder-club",
sourceFile: "src/app/admin/catalog/builder-club/page.tsx",
targetPath: "/ase/economy/catalog",
targetPath: "/admin/economy/catalog",
decision: "MERGE",
capabilities: { read: [PERMS.CATALOG_VIEW], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -122,7 +122,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/catalog/builder-club/:id",
sourceFile: "src/app/admin/catalog/builder-club/[id]/page.tsx",
targetPath: "/ase/economy/catalog/builder-club/:id",
targetPath: "/admin/economy/catalog/builder-club/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -145,7 +145,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/catalog/maintenance",
sourceFile: "src/app/admin/catalog/maintenance/page.tsx",
targetPath: "/ase/economy/catalog/maintenance",
targetPath: "/admin/economy/catalog/maintenance",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -170,7 +170,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/items",
sourceFile: "src/app/admin/items/page.tsx",
targetPath: "/ase/economy/items",
targetPath: "/admin/economy/items",
decision: "REBUILD",
capabilities: { read: [PERMS.CATALOG_VIEW], mutate: [] },
dependencies: { queries: ["fetchAdminList", "ItemsBase"], mutations: [] },
@@ -182,7 +182,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/items/:id",
sourceFile: "src/app/admin/items/[id]/page.tsx",
targetPath: "/ase/economy/items/:id",
targetPath: "/admin/economy/items/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -202,7 +202,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/shop",
sourceFile: "src/app/admin/shop/page.tsx",
targetPath: "/ase/economy/commerce/shop",
targetPath: "/admin/economy/commerce/shop",
decision: "REBUILD",
capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] },
dependencies: {
@@ -217,7 +217,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/shop/new",
sourceFile: "src/app/admin/shop/new/page.tsx",
targetPath: "/ase/economy/commerce/shop/new",
targetPath: "/admin/economy/commerce/shop/new",
decision: "REBUILD",
capabilities: {
read: [PERMS.SHOP_EDIT],
@@ -232,7 +232,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/shop/:id",
sourceFile: "src/app/admin/shop/[id]/page.tsx",
targetPath: "/ase/economy/commerce/shop/:id",
targetPath: "/admin/economy/commerce/shop/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.SHOP_VIEW],
@@ -250,7 +250,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/marketplace",
sourceFile: "src/app/admin/marketplace/page.tsx",
targetPath: "/ase/economy/commerce/marketplace",
targetPath: "/admin/economy/commerce/marketplace",
decision: "REBUILD",
capabilities: {
read: [PERMS.SHOP_VIEW],
@@ -268,7 +268,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/vouchers",
sourceFile: "src/app/admin/vouchers/page.tsx",
targetPath: "/ase/economy/commerce/vouchers",
targetPath: "/admin/economy/commerce/vouchers",
decision: "REBUILD",
capabilities: {
read: [PERMS.SHOP_VIEW],
@@ -286,7 +286,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/subscriptions",
sourceFile: "src/app/admin/subscriptions/page.tsx",
targetPath: "/ase/economy/commerce/subscriptions",
targetPath: "/admin/economy/commerce/subscriptions",
decision: "REBUILD",
capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] },
dependencies: { queries: ["users_subscriptions"], mutations: [] },
@@ -301,7 +301,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/transactions",
sourceFile: "src/app/admin/transactions/page.tsx",
targetPath: "/ase/economy/history/transactions",
targetPath: "/admin/economy/history/transactions",
decision: "REBUILD",
capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] },
dependencies: {
@@ -316,7 +316,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/rare-values",
sourceFile: "src/app/admin/rare-values/page.tsx",
targetPath: "/ase/economy/value/rare-values",
targetPath: "/admin/economy/value/rare-values",
decision: "REBUILD",
capabilities: {
read: [PERMS.SHOP_VIEW],
@@ -341,7 +341,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/badges",
sourceFile: "src/app/admin/badges/page.tsx",
targetPath: "/ase/economy/rewards/badges",
targetPath: "/admin/economy/rewards/badges",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -359,7 +359,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/achievements",
sourceFile: "src/app/admin/achievements/page.tsx",
targetPath: "/ase/economy/rewards/achievements",
targetPath: "/admin/economy/rewards/achievements",
decision: "REBUILD",
capabilities: { read: [PERMS.CATALOG_VIEW], mutate: [] },
dependencies: { queries: ["Achievements"], mutations: [] },
@@ -371,7 +371,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/sounds",
sourceFile: "src/app/admin/sounds/page.tsx",
targetPath: "/ase/economy/rewards/sounds",
targetPath: "/admin/economy/rewards/sounds",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_VIEW],
@@ -393,7 +393,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/calendar",
sourceFile: "src/app/admin/calendar/page.tsx",
targetPath: "/ase/economy/rewards/calendar",
targetPath: "/admin/economy/rewards/calendar",
decision: "REBUILD",
capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] },
dependencies: {
@@ -408,7 +408,7 @@ export const economyMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/calendar/:id",
sourceFile: "src/app/admin/calendar/[id]/page.tsx",
targetPath: "/ase/economy/rewards/calendar/:id",
targetPath: "/admin/economy/rewards/calendar/:id",
decision: "REBUILD",
capabilities: { read: [PERMS.SHOP_VIEW], mutate: [] },
dependencies: {
@@ -1,8 +1,7 @@
import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import { ownedLegacyPages, recordedLegacyPages } from "./discover-legacy-pages";
import { ownedLegacyPages } from "./discover-legacy-pages";
import { hotelMigrationEntries } from "./hotel";
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
import { validateMigrationEntries } from "./validate-matrix";
const HOTEL_PREFIXES = [
@@ -16,17 +15,14 @@ describe("hotelMigrationEntries", () => {
it("maps all hotel tools below the hotel target root", () => {
expect(
validateMigrationEntries(
ownedLegacyPages(
HOTEL_PREFIXES,
recordedLegacyPages(HOUSEKEEPING_MIGRATION_MATRIX),
),
ownedLegacyPages(HOTEL_PREFIXES),
hotelMigrationEntries,
),
).toEqual([]);
expect(
hotelMigrationEntries.every(
(row) =>
row.targetPath === null || row.targetPath.startsWith("/ase/hotel/"),
row.targetPath === null || row.targetPath.startsWith("/admin/hotel/"),
),
).toBe(true);
});
@@ -43,38 +39,36 @@ describe("hotelMigrationEntries", () => {
).toEqual([
{
legacyPath: "/admin/rooms",
targetPath: "/ase/hotel/rooms",
targetPath: "/admin/hotel/rooms",
decision: "REBUILD",
},
{
legacyPath: "/admin/rooms/:id",
targetPath: "/ase/hotel/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
},
{
legacyPath: "/admin/rooms/:id/furni",
targetPath: "/ase/hotel/rooms/:id/furni",
targetPath: "/admin/hotel/rooms/:id/furni",
decision: "REBUILD",
},
{
legacyPath: "/admin/rooms/edit/:id",
targetPath: "/ase/hotel/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
},
{
legacyPath: "/admin/rooms/show/:id",
targetPath: "/ase/hotel/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
},
]);
});
it("records concrete runtime parity evidence for every verified workflow", () => {
it("keeps every audited workflow planned without parity claims", () => {
expect(
hotelMigrationEntries.every(
(row) =>
row.status === "VERIFIED" &&
row.parityEvidence.includes(`runtime-parity:${row.legacyPath}`),
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
+31 -31
View File
@@ -14,8 +14,8 @@ function plannedHotelEntry(entry: PlannedHotelEntry): MigrationEntry {
...entry,
targetDomain: "hotel",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [`runtime-parity:${entry.legacyPath}`],
status: entry.decision === "REMOVE" ? "REMOVED" : "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
@@ -26,7 +26,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/rooms",
sourceFile: "src/app/admin/rooms/page.tsx",
targetPath: "/ase/hotel/rooms",
targetPath: "/admin/hotel/rooms",
decision: "REBUILD",
capabilities: { read: [PERMS.ROOMS_VIEW], mutate: [] },
dependencies: {
@@ -41,7 +41,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/rooms/:id",
sourceFile: "src/app/admin/rooms/[id]/page.tsx",
targetPath: "/ase/hotel/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
capabilities: { read: [PERMS.ROOMS_VIEW], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -55,7 +55,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/rooms/:id/furni",
sourceFile: "src/app/admin/rooms/[id]/furni/page.tsx",
targetPath: "/ase/hotel/rooms/:id/furni",
targetPath: "/admin/hotel/rooms/:id/furni",
decision: "REBUILD",
capabilities: {
read: [PERMS.ROOMS_VIEW],
@@ -81,7 +81,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/rooms/edit/:id",
sourceFile: "src/app/admin/rooms/edit/[id]/page.tsx",
targetPath: "/ase/hotel/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.ROOMS_EDIT],
@@ -107,7 +107,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/rooms/show/:id",
sourceFile: "src/app/admin/rooms/show/[id]/page.tsx",
targetPath: "/ase/hotel/rooms/:id",
targetPath: "/admin/hotel/rooms/:id",
decision: "MERGE",
capabilities: { read: [PERMS.ROOMS_VIEW], mutate: [] },
dependencies: { queries: ["Rooms", "User", "loadRoom"], mutations: [] },
@@ -122,7 +122,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/navigation",
sourceFile: "src/app/admin/navigation/page.tsx",
targetPath: "/ase/hotel/navigation",
targetPath: "/admin/hotel/navigation",
decision: "REBUILD",
capabilities: { read: [PERMS.PAGES_VIEW], mutate: [] },
dependencies: {
@@ -144,7 +144,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio",
sourceFile: "src/app/admin/radio/page.tsx",
targetPath: "/ase/hotel/radio/overview",
targetPath: "/admin/hotel/radio/overview",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -162,7 +162,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/api-keys",
sourceFile: "src/app/admin/radio/api-keys/page.tsx",
targetPath: "/ase/hotel/radio/api-keys",
targetPath: "/admin/hotel/radio/api-keys",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -183,7 +183,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/autodj",
sourceFile: "src/app/admin/radio/autodj/page.tsx",
targetPath: "/ase/hotel/radio/autodj",
targetPath: "/admin/hotel/radio/autodj",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -201,7 +201,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/banners",
sourceFile: "src/app/admin/radio/banners/page.tsx",
targetPath: "/ase/hotel/radio/banners",
targetPath: "/admin/hotel/radio/banners",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -223,7 +223,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/embed",
sourceFile: "src/app/admin/radio/embed/page.tsx",
targetPath: "/ase/hotel/radio/embed",
targetPath: "/admin/hotel/radio/embed",
decision: "REBUILD",
capabilities: { read: [PERMS.RADIO_VIEW], mutate: [] },
dependencies: {
@@ -238,7 +238,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/history",
sourceFile: "src/app/admin/radio/history/page.tsx",
targetPath: "/ase/hotel/radio/history",
targetPath: "/admin/hotel/radio/history",
decision: "REBUILD",
capabilities: { read: [PERMS.RADIO_VIEW], mutate: [] },
dependencies: { queries: ["RadioHistory", "User"], mutations: [] },
@@ -250,7 +250,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/moderation",
sourceFile: "src/app/admin/radio/moderation/page.tsx",
targetPath: "/ase/hotel/radio/moderation",
targetPath: "/admin/hotel/radio/moderation",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -269,7 +269,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/monitoring",
sourceFile: "src/app/admin/radio/monitoring/page.tsx",
targetPath: "/ase/hotel/radio/monitoring",
targetPath: "/admin/hotel/radio/monitoring",
decision: "REBUILD",
capabilities: { read: [PERMS.RADIO_VIEW], mutate: [] },
dependencies: {
@@ -289,7 +289,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/points",
sourceFile: "src/app/admin/radio/points/page.tsx",
targetPath: "/ase/hotel/radio/points",
targetPath: "/admin/hotel/radio/points",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -307,7 +307,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/ranks",
sourceFile: "src/app/admin/radio/ranks/page.tsx",
targetPath: "/ase/hotel/radio/ranks",
targetPath: "/admin/hotel/radio/ranks",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -325,7 +325,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/radio/settings",
sourceFile: "src/app/admin/radio/settings/page.tsx",
targetPath: "/ase/hotel/radio/settings",
targetPath: "/admin/hotel/radio/settings",
decision: "REBUILD",
capabilities: {
read: [PERMS.RADIO_VIEW],
@@ -352,7 +352,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio",
sourceFile: "src/app/admin/studio/page.tsx",
targetPath: "/ase/hotel/studio/furni",
targetPath: "/admin/hotel/studio/furni",
decision: "MERGE",
capabilities: { read: [PERMS.ASSETS_IMPORT], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -366,7 +366,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/audit",
sourceFile: "src/app/admin/studio/audit/page.tsx",
targetPath: "/ase/hotel/studio/audit",
targetPath: "/admin/hotel/studio/audit",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -396,7 +396,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/badges",
sourceFile: "src/app/admin/studio/badges/page.tsx",
targetPath: "/ase/hotel/studio/badges",
targetPath: "/admin/hotel/studio/badges",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -426,7 +426,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/clone",
sourceFile: "src/app/admin/studio/clone/page.tsx",
targetPath: "/ase/hotel/studio/clone",
targetPath: "/admin/hotel/studio/clone",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -460,7 +460,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/clothing",
sourceFile: "src/app/admin/studio/clothing/page.tsx",
targetPath: "/ase/hotel/studio/clothing",
targetPath: "/admin/hotel/studio/clothing",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -490,7 +490,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/effects",
sourceFile: "src/app/admin/studio/effects/page.tsx",
targetPath: "/ase/hotel/studio/effects",
targetPath: "/admin/hotel/studio/effects",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -513,7 +513,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/furni",
sourceFile: "src/app/admin/studio/furni/page.tsx",
targetPath: "/ase/hotel/studio/furni",
targetPath: "/admin/hotel/studio/furni",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -551,7 +551,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/maintenance",
sourceFile: "src/app/admin/studio/maintenance/page.tsx",
targetPath: "/ase/hotel/studio/maintenance",
targetPath: "/admin/hotel/studio/maintenance",
decision: "REBUILD",
capabilities: {
read: [PERMS.CATALOG_EDIT],
@@ -577,7 +577,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/pets",
sourceFile: "src/app/admin/studio/pets/page.tsx",
targetPath: "/ase/hotel/studio/pets",
targetPath: "/admin/hotel/studio/pets",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -604,7 +604,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/repair-icons",
sourceFile: "src/app/admin/studio/repair-icons/page.tsx",
targetPath: "/ase/hotel/studio/repair-icons",
targetPath: "/admin/hotel/studio/repair-icons",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -628,7 +628,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/sync",
sourceFile: "src/app/admin/studio/sync/page.tsx",
targetPath: "/ase/hotel/studio/sync",
targetPath: "/admin/hotel/studio/sync",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -653,7 +653,7 @@ export const hotelMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/studio/upload",
sourceFile: "src/app/admin/studio/upload/page.tsx",
targetPath: "/ase/hotel/studio/upload",
targetPath: "/admin/hotel/studio/upload",
decision: "REBUILD",
capabilities: {
read: [PERMS.ASSETS_IMPORT],
@@ -1,20 +1,15 @@
import { describe, expect, it } from "vitest";
import {
discoverLegacyPages,
recordedLegacyPages,
} from "./discover-legacy-pages";
import { discoverLegacyPages } from "./discover-legacy-pages";
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
import { validateMigrationEntries } from "./validate-matrix";
describe("HOUSEKEEPING_MIGRATION_MATRIX", () => {
it("keeps all 137 historical pages recorded after cutover", () => {
it("covers all 137 legacy pages exactly once", () => {
const discovered = discoverLegacyPages();
const recorded = recordedLegacyPages(HOUSEKEEPING_MIGRATION_MATRIX);
expect(HOUSEKEEPING_MIGRATION_MATRIX).toHaveLength(137);
expect(discovered).toEqual([]);
expect(
validateMigrationEntries(recorded, HOUSEKEEPING_MIGRATION_MATRIX),
validateMigrationEntries(discovered, HOUSEKEEPING_MIGRATION_MATRIX),
).toEqual([]);
});
@@ -10,7 +10,7 @@ describe("operationsMigrationEntries", () => {
legacyPath: "/admin",
sourceFile: "src/app/admin/page.tsx",
targetDomain: "operations",
targetPath: "/ase",
targetPath: "/admin/work",
decision: "REBUILD",
capabilities: { read: [PERMS.ADMIN_DASHBOARD], mutate: [] },
dependencies: {
@@ -26,8 +26,8 @@ describe("operationsMigrationEntries", () => {
localization: "COMPLETE",
accessibility: "PARTIAL",
requiredTests: ["integration", "e2e", "visual"],
parityEvidence: ["runtime-parity:/admin"],
status: "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: [
"Replace metric dashboard with capability-derived operational home",
],
@@ -7,7 +7,7 @@ export const operationsMigrationEntries: readonly MigrationEntry[] = [
legacyPath: "/admin",
sourceFile: "src/app/admin/page.tsx",
targetDomain: "operations",
targetPath: "/ase",
targetPath: "/admin/work",
decision: "REBUILD",
capabilities: { read: [PERMS.ADMIN_DASHBOARD], mutate: [] },
dependencies: {
@@ -18,8 +18,8 @@ export const operationsMigrationEntries: readonly MigrationEntry[] = [
localization: "COMPLETE",
accessibility: "PARTIAL",
requiredTests: ["integration", "e2e", "visual"],
parityEvidence: ["runtime-parity:/admin"],
status: "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: [
"Replace metric dashboard with capability-derived operational home",
],
@@ -1,6 +1,5 @@
import { describe, expect, it } from "vitest";
import { recordedLegacyPages } from "./discover-legacy-pages";
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
import { discoverLegacyPages } from "./discover-legacy-pages";
import { operationsMigrationEntries } from "./operations";
import { peopleMigrationEntries } from "./people";
import { validateMigrationEntries } from "./validate-matrix";
@@ -30,7 +29,7 @@ describe("peopleMigrationEntries", () => {
expect(modRows).toHaveLength(13);
expect(modRows.every((row) => row.decision === "MERGE")).toBe(true);
expect(
modRows.every((row) => row.targetPath?.startsWith("/ase/people/")),
modRows.every((row) => row.targetPath?.startsWith("/admin/people/")),
).toBe(true);
});
@@ -42,18 +41,16 @@ describe("peopleMigrationEntries", () => {
}
});
it("records concrete runtime parity evidence for every verified row", () => {
it("keeps planned rows free of unverified parity claims", () => {
expect(
peopleMigrationEntries.every(
(row) =>
row.status === "VERIFIED" &&
row.parityEvidence.includes(`runtime-parity:${row.legacyPath}`),
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
it("covers every Operations and People legacy page exactly once", () => {
const expected = recordedLegacyPages(HOUSEKEEPING_MIGRATION_MATRIX).filter(
const expected = discoverLegacyPages().filter(
(page) =>
page.legacyPath === "/admin" ||
PEOPLE_PREFIXES.some(
+41 -41
View File
@@ -14,8 +14,8 @@ function plannedPeopleEntry(entry: PlannedPeopleEntry): MigrationEntry {
...entry,
targetDomain: "people",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [`runtime-parity:${entry.legacyPath}`],
status: entry.decision === "REMOVE" ? "REMOVED" : "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
@@ -26,7 +26,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/users",
sourceFile: "src/app/admin/users/page.tsx",
targetPath: "/ase/people/users",
targetPath: "/admin/people/users",
decision: "REBUILD",
capabilities: {
read: [PERMS.USERS_VIEW],
@@ -50,7 +50,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/users/edit/:id",
sourceFile: "src/app/admin/users/edit/[id]/page.tsx",
targetPath: "/ase/people/users/:id/edit",
targetPath: "/admin/people/users/:id/edit",
decision: "REBUILD",
capabilities: {
read: [PERMS.USERS_EDIT],
@@ -81,7 +81,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/users/multi-accounts",
sourceFile: "src/app/admin/users/multi-accounts/page.tsx",
targetPath: "/ase/people/users/multi-accounts",
targetPath: "/admin/people/users/multi-accounts",
decision: "REBUILD",
capabilities: { read: [PERMS.USERS_VIEW], mutate: [] },
dependencies: { queries: ["detectMultiAccounts"], mutations: [] },
@@ -93,7 +93,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/users/show/:id",
sourceFile: "src/app/admin/users/show/[id]/page.tsx",
targetPath: "/ase/people/users/:id",
targetPath: "/admin/people/users/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.USERS_VIEW],
@@ -119,7 +119,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/users/:id",
sourceFile: "src/app/admin/users/[id]/page.tsx",
targetPath: "/ase/people/users/:id",
targetPath: "/admin/people/users/:id",
decision: "MERGE",
capabilities: { read: [PERMS.USERS_VIEW], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -133,7 +133,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/users/:id/edit",
sourceFile: "src/app/admin/users/[id]/edit/page.tsx",
targetPath: "/ase/people/users/:id/edit",
targetPath: "/admin/people/users/:id/edit",
decision: "MERGE",
capabilities: { read: [PERMS.USERS_EDIT], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -147,7 +147,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/online",
sourceFile: "src/app/admin/online/page.tsx",
targetPath: "/ase/people/community/online",
targetPath: "/admin/people/community/online",
decision: "REBUILD",
capabilities: { read: [PERMS.USERS_VIEW], mutate: [] },
dependencies: { queries: ["fetchAdminList", "User"], mutations: [] },
@@ -159,7 +159,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/guilds",
sourceFile: "src/app/admin/guilds/page.tsx",
targetPath: "/ase/people/community/guilds",
targetPath: "/admin/people/community/guilds",
decision: "REBUILD",
capabilities: { read: [PERMS.USERS_VIEW], mutate: [] },
dependencies: {
@@ -174,7 +174,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/guilds/:id",
sourceFile: "src/app/admin/guilds/[id]/page.tsx",
targetPath: "/ase/people/community/guilds/:id",
targetPath: "/admin/people/community/guilds/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.USERS_VIEW],
@@ -192,7 +192,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/applications",
sourceFile: "src/app/admin/applications/page.tsx",
targetPath: "/ase/people/staff/applications",
targetPath: "/admin/people/staff/applications",
decision: "REBUILD",
capabilities: {
read: [PERMS.USERS_VIEW],
@@ -212,7 +212,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/teams",
sourceFile: "src/app/admin/teams/page.tsx",
targetPath: "/ase/people/staff/teams",
targetPath: "/admin/people/staff/teams",
decision: "REBUILD",
capabilities: {
read: [PERMS.USERS_VIEW],
@@ -230,7 +230,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/moderation",
sourceFile: "src/app/admin/moderation/page.tsx",
targetPath: "/ase/people/moderation",
targetPath: "/admin/people/moderation",
decision: "REBUILD",
capabilities: { read: [PERMS.MODERATION_VIEW], mutate: [] },
dependencies: {
@@ -251,7 +251,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/moderation/actions",
sourceFile: "src/app/admin/moderation/actions/page.tsx",
targetPath: "/ase/people/moderation/actions",
targetPath: "/admin/people/moderation/actions",
decision: "REBUILD",
capabilities: {
read: [PERMS.MODERATION_EDIT],
@@ -276,7 +276,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/moderation/cfh",
sourceFile: "src/app/admin/moderation/cfh/page.tsx",
targetPath: "/ase/people/moderation/cfh",
targetPath: "/admin/people/moderation/cfh",
decision: "REBUILD",
capabilities: { read: [PERMS.MODERATION_VIEW], mutate: [] },
dependencies: { queries: ["SupportTickets", "User"], mutations: [] },
@@ -288,7 +288,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/moderation/cfh/:id",
sourceFile: "src/app/admin/moderation/cfh/[id]/page.tsx",
targetPath: "/ase/people/moderation/cfh/:id",
targetPath: "/admin/people/moderation/cfh/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.MODERATION_VIEW],
@@ -313,7 +313,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/moderation/team",
sourceFile: "src/app/admin/moderation/team/page.tsx",
targetPath: "/ase/people/staff/moderation-team",
targetPath: "/admin/people/staff/moderation-team",
decision: "REBUILD",
capabilities: { read: [PERMS.MODERATION_VIEW], mutate: [] },
dependencies: {
@@ -334,7 +334,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/bans",
sourceFile: "src/app/admin/bans/page.tsx",
targetPath: "/ase/people/moderation/bans",
targetPath: "/admin/people/moderation/bans",
decision: "REBUILD",
capabilities: {
read: [PERMS.BANS_VIEW],
@@ -352,7 +352,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/ip",
sourceFile: "src/app/admin/ip/page.tsx",
targetPath: "/ase/people/moderation/ip",
targetPath: "/admin/people/moderation/ip",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -375,7 +375,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/vpn",
sourceFile: "src/app/admin/vpn/page.tsx",
targetPath: "/ase/people/moderation/vpn",
targetPath: "/admin/people/moderation/vpn",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -393,7 +393,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/wordfilter",
sourceFile: "src/app/admin/wordfilter/page.tsx",
targetPath: "/ase/people/moderation/word-filter",
targetPath: "/admin/people/moderation/word-filter",
decision: "REBUILD",
capabilities: {
read: [PERMS.WORDFILTER_VIEW],
@@ -413,7 +413,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/tickets",
sourceFile: "src/app/admin/tickets/page.tsx",
targetPath: "/ase/people/support/tickets",
targetPath: "/admin/people/support/tickets",
decision: "REBUILD",
capabilities: { read: [PERMS.TICKETS_VIEW], mutate: [] },
dependencies: {
@@ -428,7 +428,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/tickets/desk",
sourceFile: "src/app/admin/tickets/desk/page.tsx",
targetPath: "/ase/people/support/tickets/desk",
targetPath: "/admin/people/support/tickets/desk",
decision: "REBUILD",
capabilities: { read: [PERMS.TICKETS_VIEW], mutate: [] },
dependencies: {
@@ -443,7 +443,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/tickets/templates",
sourceFile: "src/app/admin/tickets/templates/page.tsx",
targetPath: "/ase/people/support/tickets/templates",
targetPath: "/admin/people/support/tickets/templates",
decision: "REBUILD",
capabilities: {
read: [PERMS.TICKETS_EDIT],
@@ -461,7 +461,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/tickets/:id",
sourceFile: "src/app/admin/tickets/[id]/page.tsx",
targetPath: "/ase/people/support/tickets/:id",
targetPath: "/admin/people/support/tickets/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.TICKETS_VIEW],
@@ -489,7 +489,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/help-tickets",
sourceFile: "src/app/admin/help-tickets/page.tsx",
targetPath: "/ase/people/support/help-tickets",
targetPath: "/admin/people/support/help-tickets",
decision: "REBUILD",
capabilities: { read: [PERMS.TICKETS_VIEW], mutate: [] },
dependencies: {
@@ -509,7 +509,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/help-tickets/:id",
sourceFile: "src/app/admin/help-tickets/[id]/page.tsx",
targetPath: "/ase/people/support/help-tickets/:id",
targetPath: "/admin/people/support/help-tickets/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.TICKETS_VIEW],
@@ -542,7 +542,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod",
sourceFile: "src/app/mod/page.tsx",
targetPath: "/ase/people/moderation",
targetPath: "/admin/people/moderation",
decision: "MERGE",
capabilities: {
read: [
@@ -580,7 +580,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/actions",
sourceFile: "src/app/mod/actions/page.tsx",
targetPath: "/ase/people/moderation/actions",
targetPath: "/admin/people/moderation/actions",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_ACTIONS, PERMS.MODERATION_EDIT],
@@ -605,7 +605,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/bans",
sourceFile: "src/app/mod/bans/page.tsx",
targetPath: "/ase/people/moderation/bans",
targetPath: "/admin/people/moderation/bans",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_BANS_VIEW, PERMS.BANS_VIEW],
@@ -620,7 +620,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/cfh",
sourceFile: "src/app/mod/cfh/page.tsx",
targetPath: "/ase/people/moderation/cfh",
targetPath: "/admin/people/moderation/cfh",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_CFH_VIEW, PERMS.MODERATION_VIEW],
@@ -635,7 +635,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/cfh/:id",
sourceFile: "src/app/mod/cfh/[id]/page.tsx",
targetPath: "/ase/people/moderation/cfh/:id",
targetPath: "/admin/people/moderation/cfh/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_CFH_VIEW, PERMS.MODERATION_VIEW],
@@ -660,7 +660,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/help-tickets",
sourceFile: "src/app/mod/help-tickets/page.tsx",
targetPath: "/ase/people/support/help-tickets",
targetPath: "/admin/people/support/help-tickets",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW],
@@ -683,7 +683,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/help-tickets/:id",
sourceFile: "src/app/mod/help-tickets/[id]/page.tsx",
targetPath: "/ase/people/support/help-tickets/:id",
targetPath: "/admin/people/support/help-tickets/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW],
@@ -712,7 +712,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/team",
sourceFile: "src/app/mod/team/page.tsx",
targetPath: "/ase/people/staff/moderation-team",
targetPath: "/admin/people/staff/moderation-team",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_TEAM_VIEW, PERMS.MODERATION_VIEW],
@@ -736,7 +736,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/tickets",
sourceFile: "src/app/mod/tickets/page.tsx",
targetPath: "/ase/people/support/tickets",
targetPath: "/admin/people/support/tickets",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW],
@@ -754,7 +754,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/tickets/desk",
sourceFile: "src/app/mod/tickets/desk/page.tsx",
targetPath: "/ase/people/support/tickets/desk",
targetPath: "/admin/people/support/tickets/desk",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW],
@@ -777,7 +777,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/tickets/:id",
sourceFile: "src/app/mod/tickets/[id]/page.tsx",
targetPath: "/ase/people/support/tickets/:id",
targetPath: "/admin/people/support/tickets/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_TICKETS_VIEW, PERMS.TICKETS_VIEW],
@@ -806,7 +806,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/users",
sourceFile: "src/app/mod/users/page.tsx",
targetPath: "/ase/people/users",
targetPath: "/admin/people/users",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_USERS_VIEW, PERMS.USERS_VIEW],
@@ -821,7 +821,7 @@ export const peopleMigrationEntries: readonly MigrationEntry[] = [
surface: "mod",
legacyPath: "/mod/users/:id",
sourceFile: "src/app/mod/users/[id]/page.tsx",
targetPath: "/ase/people/users/:id",
targetPath: "/admin/people/users/:id",
decision: "MERGE",
capabilities: {
read: [PERMS.MOD_USERS_VIEW, PERMS.USERS_VIEW],
@@ -1,7 +1,6 @@
import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import { ownedLegacyPages, recordedLegacyPages } from "./discover-legacy-pages";
import { HOUSEKEEPING_MIGRATION_MATRIX } from "./matrix";
import { ownedLegacyPages } from "./discover-legacy-pages";
import { systemMigrationEntries } from "./system";
import { validateMigrationEntries } from "./validate-matrix";
@@ -24,10 +23,7 @@ describe("systemMigrationEntries", () => {
expect(systemMigrationEntries).toHaveLength(19);
expect(
validateMigrationEntries(
ownedLegacyPages(
SYSTEM_PREFIXES,
recordedLegacyPages(HOUSEKEEPING_MIGRATION_MATRIX),
),
ownedLegacyPages(SYSTEM_PREFIXES),
systemMigrationEntries,
),
).toEqual([]);
@@ -54,7 +50,7 @@ describe("systemMigrationEntries", () => {
expect(systemMigrationEntries).toContainEqual(
expect.objectContaining({
legacyPath: "/admin/permissions",
targetPath: "/ase/system/access/permissions",
targetPath: "/admin/system/access/permissions",
decision: expect.not.stringMatching("REMOVE"),
}),
);
@@ -79,10 +75,10 @@ describe("systemMigrationEntries", () => {
it("uses only the approved System target roots", () => {
const allowedRoots = [
"/ase/system/access",
"/ase/system/configuration",
"/ase/system/observability",
"/ase/system/operations",
"/admin/system/access",
"/admin/system/configuration",
"/admin/system/observability",
"/admin/system/operations",
];
expect(
@@ -97,13 +93,13 @@ describe("systemMigrationEntries", () => {
).toBe(true);
});
it("records verified or removed status with concrete runtime evidence", () => {
it("keeps non-removal workflows planned without parity claims", () => {
expect(
systemMigrationEntries.every(
(row) =>
row.status === (row.decision === "REMOVE" ? "REMOVED" : "VERIFIED") &&
row.parityEvidence.includes(`runtime-parity:${row.legacyPath}`),
),
systemMigrationEntries
.filter((row) => row.decision !== "REMOVE")
.every(
(row) => row.status === "PLANNED" && row.parityEvidence.length === 0,
),
).toBe(true);
});
+19 -19
View File
@@ -14,8 +14,8 @@ function plannedSystemEntry(entry: PlannedSystemEntry): MigrationEntry {
...entry,
targetDomain: "system",
requiredTests: entry.requiredTests ?? ["integration", "e2e", "visual"],
parityEvidence: [`runtime-parity:${entry.legacyPath}`],
status: entry.decision === "REMOVE" ? "REMOVED" : "VERIFIED",
parityEvidence: [],
status: "PLANNED",
notes: entry.notes ?? [],
};
}
@@ -26,7 +26,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/alerts",
sourceFile: "src/app/admin/alerts/page.tsx",
targetPath: "/ase/system/operations/alerts",
targetPath: "/admin/system/operations/alerts",
decision: "REBUILD",
capabilities: {
read: [PERMS.NOTIFICATIONS_VIEW],
@@ -51,7 +51,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/analytics",
sourceFile: "src/app/admin/analytics/page.tsx",
targetPath: "/ase/system/observability/analytics",
targetPath: "/admin/system/observability/analytics",
decision: "REBUILD",
capabilities: { read: [PERMS.ANALYTICS_VIEW], mutate: [] },
dependencies: {
@@ -73,7 +73,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/analytics/activity",
sourceFile: "src/app/admin/analytics/activity/page.tsx",
targetPath: "/ase/system/observability/analytics/activity",
targetPath: "/admin/system/observability/analytics/activity",
decision: "REBUILD",
capabilities: { read: [PERMS.ANALYTICS_VIEW], mutate: [] },
dependencies: {
@@ -96,7 +96,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/analytics/economy",
sourceFile: "src/app/admin/analytics/economy/page.tsx",
targetPath: "/ase/system/observability/analytics/economy",
targetPath: "/admin/system/observability/analytics/economy",
decision: "REBUILD",
capabilities: { read: [PERMS.ANALYTICS_VIEW], mutate: [] },
dependencies: {
@@ -120,7 +120,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/commandocentrum",
sourceFile: "src/app/admin/commandocentrum/page.tsx",
targetPath: "/ase/system/operations/command-center",
targetPath: "/admin/system/operations/command-center",
decision: "REBUILD",
capabilities: {
read: [PERMS.RCON_EXECUTE],
@@ -164,7 +164,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/devops",
sourceFile: "src/app/admin/devops/page.tsx",
targetPath: "/ase/system/observability/devops",
targetPath: "/admin/system/observability/devops",
decision: "REBUILD",
capabilities: { read: [PERMS.DEVOPS_VIEW], mutate: [] },
dependencies: {
@@ -185,7 +185,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/devops/errors",
sourceFile: "src/app/admin/devops/errors/page.tsx",
targetPath: "/ase/system/observability/devops/errors",
targetPath: "/admin/system/observability/devops/errors",
decision: "REBUILD",
capabilities: { read: [PERMS.DEVOPS_VIEW], mutate: [] },
dependencies: { queries: ["EmulatorErrors"], mutations: [] },
@@ -197,7 +197,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/emulator",
sourceFile: "src/app/admin/emulator/page.tsx",
targetPath: "/ase/system/configuration/emulator",
targetPath: "/admin/system/configuration/emulator",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -248,7 +248,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/logs",
sourceFile: "src/app/admin/logs/page.tsx",
targetPath: "/ase/system/observability/logs/staff",
targetPath: "/admin/system/observability/logs/staff",
decision: "REBUILD",
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
dependencies: { queries: ["StaffActivities", "User"], mutations: [] },
@@ -260,7 +260,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/logs/audit",
sourceFile: "src/app/admin/logs/audit/page.tsx",
targetPath: "/ase/system/observability/logs/audit",
targetPath: "/admin/system/observability/logs/audit",
decision: "REBUILD",
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
dependencies: { queries: ["getAuditLogs"], mutations: [] },
@@ -272,7 +272,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/logs/chat",
sourceFile: "src/app/admin/logs/chat/page.tsx",
targetPath: "/ase/system/observability/logs/chat",
targetPath: "/admin/system/observability/logs/chat",
decision: "REBUILD",
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
dependencies: {
@@ -287,7 +287,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/logs/commands",
sourceFile: "src/app/admin/logs/commands/page.tsx",
targetPath: "/ase/system/observability/logs/commands",
targetPath: "/admin/system/observability/logs/commands",
decision: "REBUILD",
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
dependencies: {
@@ -302,7 +302,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/logs/trades",
sourceFile: "src/app/admin/logs/trades/page.tsx",
targetPath: "/ase/system/observability/logs/trades",
targetPath: "/admin/system/observability/logs/trades",
decision: "REBUILD",
capabilities: { read: [PERMS.LOGS_VIEW], mutate: [] },
dependencies: {
@@ -319,7 +319,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/maintenance",
sourceFile: "src/app/admin/maintenance/page.tsx",
targetPath: "/ase/system/operations/maintenance",
targetPath: "/admin/system/operations/maintenance",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -360,7 +360,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/permissions",
sourceFile: "src/app/admin/permissions/page.tsx",
targetPath: "/ase/system/access/permissions",
targetPath: "/admin/system/access/permissions",
decision: "REBUILD",
capabilities: {
read: [PERMS.PERMISSIONS_MANAGE],
@@ -384,7 +384,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/permissions/:id",
sourceFile: "src/app/admin/permissions/[id]/page.tsx",
targetPath: "/ase/system/access/permissions/:id",
targetPath: "/admin/system/access/permissions/:id",
decision: "REBUILD",
capabilities: {
read: [PERMS.PERMISSIONS_MANAGE],
@@ -416,7 +416,7 @@ export const systemMigrationEntries: readonly MigrationEntry[] = [
surface: "admin",
legacyPath: "/admin/settings",
sourceFile: "src/app/admin/settings/page.tsx",
targetPath: "/ase/system/configuration/settings",
targetPath: "/admin/system/configuration/settings",
decision: "REBUILD",
capabilities: {
read: [PERMS.SETTINGS_VIEW],
@@ -11,7 +11,7 @@ const page = (legacyPath: string): LegacyPage => ({
const entry = (legacyPath: string): MigrationEntry => ({
...page(legacyPath),
targetDomain: "system",
targetPath: "/ase/system/example",
targetPath: "/admin/system/example",
decision: "REHOST",
capabilities: { read: ["admin.dashboard"], mutate: [] },
dependencies: { queries: [], mutations: [] },
@@ -112,7 +112,7 @@ describe("validateMigrationEntries", () => {
"MERGE requires requiredTests: /admin",
"mutation dependencies require auditRequirement: /admin",
"mutation dependencies require mutate capabilities: /admin",
"non-REMOVE targetPath must use /ase: /admin",
"non-REMOVE targetPath must start with /admin/: /admin",
"prohibited placeholder: /admin",
"VERIFIED requires parityEvidence: /admin",
]);
@@ -134,19 +134,3 @@ describe("validateMigrationEntries", () => {
).toEqual(["REHOST requires targetPath: /admin"]);
});
});
it("requires non-removal targets to use the ase namespace", () => {
expect(
validateMigrationEntries(
[page("/admin")],
[{ ...entry("/admin"), targetPath: "/ase/system/example" }],
),
).toEqual([]);
expect(
validateMigrationEntries(
[page("/admin")],
[{ ...entry("/admin"), targetPath: "/admin/system/example" }],
),
).toContain("non-REMOVE targetPath must use /ase: /admin");
});
@@ -84,9 +84,11 @@ export function validateMigrationEntries(
if (
entry.targetPath !== null &&
entry.decision !== "REMOVE" &&
!(entry.targetPath === "/ase" || entry.targetPath.startsWith("/ase/"))
!entry.targetPath.startsWith("/admin/")
) {
issues.add(`non-REMOVE targetPath must use /ase: ${legacyPath}`);
issues.add(
`non-REMOVE targetPath must start with /admin/: ${legacyPath}`,
);
}
if (