fix(finalist): program-scope guards on enroll/unenroll (code review)
- enrollFinalists: reject a roundId whose competition belongs to a different program than input.programId. - unenroll: reject a project/round pair from different programs before any delete. - Hoist ADMIN_CONFIRM attendee validation to a pre-pass so a bad entry in a multi-team batch fails before any project is partially written. - Add regression tests for both cross-program guards. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -316,6 +316,31 @@ describe('finalist.enrollFinalists', () => {
|
||||
}),
|
||||
).rejects.toThrow(/cap/i)
|
||||
})
|
||||
|
||||
it('rejects a roundId that belongs to a different program', async () => {
|
||||
const admin = await createTestUser('SUPER_ADMIN')
|
||||
userIds.push(admin.id)
|
||||
|
||||
const a = await setupEnrollFixture(`enroll-xprogram-a-${uid()}`)
|
||||
const b = await setupEnrollFixture(`enroll-xprogram-b-${uid()}`)
|
||||
programIds.push(a.program.id, b.program.id)
|
||||
userIds.push(a.lead.id, a.member.id, b.lead.id, b.member.id)
|
||||
|
||||
const caller = createCaller(finalistRouter, {
|
||||
id: admin.id,
|
||||
email: admin.email,
|
||||
role: 'SUPER_ADMIN',
|
||||
})
|
||||
|
||||
// Program A's project + Program B's LIVE_FINAL round → must be rejected.
|
||||
await expect(
|
||||
caller.enrollFinalists({
|
||||
programId: a.program.id,
|
||||
roundId: b.liveFinalRound.id,
|
||||
enrollments: [{ projectId: a.project.id, mode: 'EMAIL' }],
|
||||
}),
|
||||
).rejects.toThrow(/does not belong to this program/i)
|
||||
})
|
||||
})
|
||||
|
||||
// ─── finalist.listEnrollmentCandidates ────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user