/** * U-010: Award Governance — Unauthorized AWARD_MASTER * * Tests that non-AWARD_MASTER users cannot call finalizeWinners. */ import { describe, it, expect, beforeAll, afterAll } from 'vitest' import { prisma, createTestContext } from '../setup' import { createTestUser, createTestProgram, createTestPipeline, createTestTrack, createTestStage, createTestProject, cleanupTestData, } from '../helpers' import { awardRouter } from '@/server/routers/award' let programId: string let userIds: string[] = [] beforeAll(async () => { const program = await createTestProgram({ name: 'Award Gov Test' }) programId = program.id }) afterAll(async () => { await cleanupTestData(programId, userIds) }) describe('U-010: Award Governance — Unauthorized AWARD_MASTER', () => { it('rejects finalizeWinners when called by a JURY_MEMBER', async () => { const jury = await createTestUser('JURY_MEMBER', { name: 'Unauthorized Jury' }) userIds.push(jury.id) // Create award track infrastructure using admin const admin = await createTestUser('SUPER_ADMIN') userIds.push(admin.id) const pipeline = await createTestPipeline(programId) const track = await prisma.track.create({ data: { pipelineId: pipeline.id, name: 'Award Track', slug: `award-${Date.now()}`, kind: 'AWARD', sortOrder: 1, decisionMode: 'AWARD_MASTER_DECISION', }, }) const stage = await createTestStage(track.id, { name: 'Award Stage', stageType: 'EVALUATION', status: 'STAGE_ACTIVE', }) // Create a SpecialAward linked to the track const award = await prisma.specialAward.create({ data: { programId, name: 'Best Innovation', trackId: track.id, status: 'VOTING_OPEN', scoringMode: 'PICK_WINNER', sortOrder: 0, }, }) // Create an eligible project const project = await createTestProject(programId, { title: 'Award Project' }) await prisma.awardEligibility.create({ data: { awardId: award.id, projectId: project.id, eligible: true, method: 'MANUAL', }, }) // Attempt to call finalizeWinners as JURY_MEMBER — should be rejected const juryCtx = createTestContext(jury) const juryCaller = awardRouter.createCaller(juryCtx) await expect( juryCaller.finalizeWinners({ trackId: track.id, winnerProjectId: project.id, }) ).rejects.toThrow() // Should throw FORBIDDEN or UNAUTHORIZED // Verify the award still has no winner const unchangedAward = await prisma.specialAward.findUnique({ where: { id: award.id }, }) expect(unchangedAward!.winnerProjectId).toBeNull() }) it('allows SUPER_ADMIN to finalize winners (awardMasterProcedure permits)', async () => { const admin = await createTestUser('SUPER_ADMIN', { name: 'Admin Award Master' }) userIds.push(admin.id) const pipeline = await createTestPipeline(programId) const track = await prisma.track.create({ data: { pipelineId: pipeline.id, name: 'Admin Award Track', slug: `admin-award-${Date.now()}`, kind: 'AWARD', sortOrder: 2, decisionMode: 'AWARD_MASTER_DECISION', }, }) await createTestStage(track.id, { name: 'Admin Award Stage', stageType: 'EVALUATION', status: 'STAGE_ACTIVE', }) const award = await prisma.specialAward.create({ data: { programId, name: 'Admin Award', trackId: track.id, status: 'VOTING_OPEN', scoringMode: 'PICK_WINNER', sortOrder: 0, }, }) const project = await createTestProject(programId, { title: 'Winning Project' }) await prisma.awardEligibility.create({ data: { awardId: award.id, projectId: project.id, eligible: true, method: 'MANUAL', }, }) const adminCtx = createTestContext(admin) const adminCaller = awardRouter.createCaller(adminCtx) const result = await adminCaller.finalizeWinners({ trackId: track.id, winnerProjectId: project.id, }) expect(result.winnerProjectId).toBe(project.id) expect(result.status).toBe('CLOSED') }) })