forked from EduCraft/curriculum-project-hub
fix(hub): mark bootstrap Inbox as SYSTEM_INBOX
Alpha silo bootstrap created the root Inbox without kind=SYSTEM_INBOX, so Feishu card project creation tried to insert a second Inbox and hit the sibling-name unique index. Tag the bootstrap folder correctly and promote any legacy root Inbox on ensure.
This commit is contained in:
@@ -101,6 +101,43 @@ describe("ADR-0021 project onboarding", () => {
|
||||
]));
|
||||
});
|
||||
|
||||
it("promotes a legacy root Inbox when Feishu chat creates a project", async () => {
|
||||
await seedUser("u-member", "ou_member", "MEMBER");
|
||||
// Production drift after bootstrap omitted kind=SYSTEM_INBOX. The protect
|
||||
// trigger refuses demotion, so the test plants the legacy shape directly.
|
||||
await prisma.$executeRawUnsafe(`ALTER TABLE "Folder" DISABLE TRIGGER cph_protect_system_inbox`);
|
||||
try {
|
||||
await prisma.folder.updateMany({
|
||||
where: { organizationId: DEFAULT_ORG_ID, kind: "SYSTEM_INBOX", archivedAt: null },
|
||||
data: { kind: "REGULAR" },
|
||||
});
|
||||
} finally {
|
||||
await prisma.$executeRawUnsafe(`ALTER TABLE "Folder" ENABLE TRIGGER cph_protect_system_inbox`);
|
||||
}
|
||||
const legacy = await prisma.folder.findFirstOrThrow({
|
||||
where: { organizationId: DEFAULT_ORG_ID, parentId: null, name: "Inbox", archivedAt: null },
|
||||
select: { id: true, kind: true },
|
||||
});
|
||||
expect(legacy.kind).toBe("REGULAR");
|
||||
|
||||
const result = await createProjectFromFeishuChat(prisma, {
|
||||
organizationId: DEFAULT_ORG_ID,
|
||||
actorFeishuOpenId: "ou_member",
|
||||
chatId: "chat-legacy-inbox",
|
||||
name: "Recovered Inbox Project",
|
||||
workspaceRoot: await tempWorkspaceRoot(),
|
||||
});
|
||||
|
||||
expect(result.folderId).toBe(legacy.id);
|
||||
await expect(prisma.folder.findUniqueOrThrow({
|
||||
where: { id: legacy.id },
|
||||
select: { kind: true },
|
||||
})).resolves.toEqual({ kind: "SYSTEM_INBOX" });
|
||||
expect(await prisma.folder.count({
|
||||
where: { organizationId: DEFAULT_ORG_ID, name: "Inbox", archivedAt: null },
|
||||
})).toBe(1);
|
||||
});
|
||||
|
||||
it("blocks ordinary Feishu project creation when the org setting is off", async () => {
|
||||
await seedUser("u-member", "ou_member", "MEMBER");
|
||||
await setMembersCanCreateProjects(prisma, {
|
||||
|
||||
@@ -62,6 +62,11 @@ describe("Alpha Silo bootstrap", () => {
|
||||
{ roleId: "draft", label: "草稿", isDefault: true },
|
||||
{ roleId: "review", label: "审校", isDefault: false },
|
||||
]);
|
||||
await expect(prisma.folder.findMany({
|
||||
where: { organizationId: "org_alpha", archivedAt: null },
|
||||
select: { name: true, kind: true, parentId: true },
|
||||
})).resolves.toEqual([{ name: "Inbox", kind: "SYSTEM_INBOX", parentId: null }]);
|
||||
|
||||
|
||||
const persisted = JSON.stringify({
|
||||
feishu: await prisma.feishuApplicationCredentialVersion.findMany(),
|
||||
|
||||
Reference in New Issue
Block a user