fix: bootstrap fresh alpha silo

This commit is contained in:
2026-07-11 01:40:20 +08:00
parent cb1a9e823a
commit 38d9a9c6cb
5 changed files with 174 additions and 3 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@paradigm/hub",
"version": "0.0.3",
"version": "0.0.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@paradigm/hub",
"version": "0.0.3",
"version": "0.0.4",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.3.202",
"@fastify/cookie": "^11.0.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@paradigm/hub",
"version": "0.0.3",
"version": "0.0.4",
"private": true,
"type": "module",
"engines": {
+58
View File
@@ -49,6 +49,7 @@ export async function bootstrapAlphaSilo(
} = {},
): Promise<AlphaSiloBootstrapResult> {
const normalized = validateInput(input);
await removePristineLegacyMigrationOrganization(prisma);
const existing = await loadExistingSilo(prisma, normalized.organization.id, normalized.owner.openId);
let initialized = false;
let ownerUserId: string;
@@ -113,6 +114,63 @@ export async function bootstrapAlphaSilo(
};
}
const LEGACY_MIGRATION_ORGANIZATION = {
id: "org_default",
slug: "legacy-default",
name: "Legacy Default Organization",
inboxId: "folder_inbox_2b99350e0db97ad0cbcb55c20ee8bafa",
} as const;
/**
* A fresh database still receives the compatibility Organization inserted by
* the tenant-root migration, plus its later default settings and Inbox. An
* Alpha Silo bootstrap may replace only that exact, otherwise-unused scaffold.
* Any tenant data or shape drift remains a hard manual-repair error.
*/
async function removePristineLegacyMigrationOrganization(prisma: PrismaClient): Promise<void> {
await prisma.$transaction(async (tx) => {
const organization = await tx.organization.findUnique({
where: { id: LEGACY_MIGRATION_ORGANIZATION.id },
include: {
memberships: { take: 1, select: { id: true } },
projects: { take: 1, select: { id: true } },
teams: { take: 1, select: { id: true } },
externalDirectoryConnections: { take: 1, select: { id: true } },
providerConnections: { take: 1, select: { id: true } },
feishuApplicationConnection: { select: { id: true } },
auditEntries: { take: 1, select: { id: true } },
projectSettings: true,
folders: {
take: 2,
select: { id: true, parentId: true, name: true, sortKey: true, archivedAt: true },
},
},
});
if (organization === null) return;
const pristine =
organization.slug === LEGACY_MIGRATION_ORGANIZATION.slug &&
organization.name === LEGACY_MIGRATION_ORGANIZATION.name &&
organization.status === "ACTIVE" &&
organization.memberships.length === 0 &&
organization.projects.length === 0 &&
organization.teams.length === 0 &&
organization.externalDirectoryConnections.length === 0 &&
organization.providerConnections.length === 0 &&
organization.feishuApplicationConnection === null &&
organization.auditEntries.length === 0 &&
organization.projectSettings?.membersCanCreateProjects === true &&
organization.folders.length === 1 &&
organization.folders[0]?.id === LEGACY_MIGRATION_ORGANIZATION.inboxId &&
organization.folders[0].parentId === null &&
organization.folders[0].name === "Inbox" &&
organization.folders[0].sortKey === "000000" &&
organization.folders[0].archivedAt === null;
if (pristine) {
await tx.organization.delete({ where: { id: organization.id } });
}
});
}
async function ensureBootstrapTeams(
prisma: PrismaClient,
organizationId: string,
@@ -18,6 +18,21 @@ const input = {
describe("Alpha Silo bootstrap", () => {
beforeEach(async () => {
await prisma.$executeRawUnsafe(`TRUNCATE TABLE "Organization" RESTART IDENTITY CASCADE`);
await prisma.organization.create({
data: {
id: "org_default",
slug: "legacy-default",
name: "Legacy Default Organization",
projectSettings: { create: { membersCanCreateProjects: true } },
folders: {
create: {
id: "folder_inbox_2b99350e0db97ad0cbcb55c20ee8bafa",
name: "Inbox",
sortKey: "000000",
},
},
},
});
});
afterAll(async () => {
@@ -54,4 +69,21 @@ describe("Alpha Silo bootstrap", () => {
});
await expect(requireSiloOrganization(prisma, "org_other")).rejects.toThrow("Silo Organization mismatch");
});
it("does not delete a legacy migration Organization that contains tenant data", async () => {
await prisma.project.create({
data: {
organizationId: "org_default",
folderId: "folder_inbox_2b99350e0db97ad0cbcb55c20ee8bafa",
name: "Legacy Project",
workspaceDir: "legacy-project",
},
});
await expect(bootstrapAlphaSilo(prisma, testSecretEnvelope, input, {
feishu: async () => {},
provider: async () => {},
})).rejects.toThrow("bootstrap database is not the configured single-Organization Silo");
await expect(prisma.organization.findUnique({ where: { id: "org_default" } })).resolves.not.toBeNull();
});
});