import { describe, it, expect, vi, beforeEach } from 'vitest'; import { bootstrapUngatedGlobal, UNGATED_GLOBAL_PROJECT_NAME, SETTING_UNGATED_GLOBAL_SEEDED, } from '../src/bootstrap/ungated-global.js'; import { SYSTEM_SETTINGS_SECRET } from '../src/bootstrap/system-settings.js'; import type { PrismaClient } from '@prisma/client'; function mockPrisma(opts: { settingsData?: Record | null } = {}): PrismaClient { const secretRow = opts.settingsData ? { id: 'secret-1', name: SYSTEM_SETTINGS_SECRET, data: opts.settingsData, version: 3 } : null; return { secret: { findUnique: vi.fn(async () => secretRow), update: vi.fn(async () => ({})), create: vi.fn(async () => ({})), }, secretBackend: { findUnique: vi.fn(async () => ({ id: 'backend-default', name: 'default', isDefault: true })), findFirst: vi.fn(async () => ({ id: 'backend-default', name: 'default', isDefault: true })), }, user: { upsert: vi.fn(async () => ({ id: 'sys-user-id', email: 'system@mcpctl.local' })), }, project: { upsert: vi.fn(async (args: { where: { name: string } }) => ({ id: 'proj-ug', name: args.where.name })), }, mcpServer: { upsert: vi.fn(async (args: { where: { name: string } }) => ({ id: 'srv-calc', name: args.where.name })), }, projectServer: { upsert: vi.fn(async () => ({})), }, } as unknown as PrismaClient; } describe('bootstrapUngatedGlobal', () => { let prisma: PrismaClient; beforeEach(() => { prisma = mockPrisma(); }); it('seeds the ungated-global project with the calcmcp server and attaches it', async () => { await bootstrapUngatedGlobal(prisma); expect(prisma.project.upsert).toHaveBeenCalledWith( expect.objectContaining({ where: { name: UNGATED_GLOBAL_PROJECT_NAME }, create: expect.objectContaining({ gated: false, prompt: expect.stringContaining('calcmcp') }), }), ); expect(prisma.mcpServer.upsert).toHaveBeenCalledWith( expect.objectContaining({ where: { name: 'calcmcp' }, create: expect.objectContaining({ dockerImage: expect.stringContaining('calcmcp'), transport: 'STDIO', }), }), ); expect(prisma.projectServer.upsert).toHaveBeenCalledWith( expect.objectContaining({ where: { projectId_serverId: { projectId: 'proj-ug', serverId: 'srv-calc' } }, }), ); }); it('marks the seed as done in the system settings secret', async () => { await bootstrapUngatedGlobal(prisma); // Settings secret didn't exist → created with the marker key and a valid backend FK expect(prisma.secret.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ name: SYSTEM_SETTINGS_SECRET, backendId: 'backend-default', data: expect.objectContaining({ [SETTING_UNGATED_GLOBAL_SEEDED]: true }), }), }), ); }); it('does NOT re-seed when the marker is set (deletions stay deleted)', async () => { prisma = mockPrisma({ settingsData: { [SETTING_UNGATED_GLOBAL_SEEDED]: true } }); await bootstrapUngatedGlobal(prisma); expect(prisma.project.upsert).not.toHaveBeenCalled(); expect(prisma.mcpServer.upsert).not.toHaveBeenCalled(); expect(prisma.projectServer.upsert).not.toHaveBeenCalled(); expect(prisma.secret.update).not.toHaveBeenCalled(); expect(prisma.secret.create).not.toHaveBeenCalled(); }); it('preserves existing settings keys when writing the marker', async () => { prisma = mockPrisma({ settingsData: { allowSelfPasswordChange: false } }); await bootstrapUngatedGlobal(prisma); expect(prisma.secret.update).toHaveBeenCalledWith( expect.objectContaining({ where: { name: SYSTEM_SETTINGS_SECRET }, data: expect.objectContaining({ data: { allowSelfPasswordChange: false, [SETTING_UNGATED_GLOBAL_SEEDED]: true, }, version: 4, }), }), ); }); });