10 KiB
Mentoring & Document Lifecycle
Overview
This document covers two interconnected systems: (1) the multi-round document lifecycle that governs how submissions flow through the competition, and (2) the mentoring workspace that provides a collaboration layer for finalist teams with assigned mentors.
Part 1: Document Lifecycle
SubmissionWindow
Each round that requires document collection has an associated SubmissionWindow. A competition can have multiple windows (e.g., Round 1 application docs, Round 2 semifinal docs).
model SubmissionWindow {
id String @id @default(cuid())
competitionId String
roundId String
label String // "Round 1 Application Documents", "Round 2 Semifinal Documents"
opensAt DateTime
closesAt DateTime
deadlinePolicy DeadlinePolicy @default(HARD)
gracePeriodMinutes Int? // only used with GRACE policy
lockOnClose Boolean @default(true) // automatically lock submissions when window closes
isLocked Boolean @default(false) // manual lock toggle (admin can lock before close)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
competition Competition @relation(...)
round Round @relation(...)
requirements SubmissionFileRequirement[]
@@index([competitionId])
@@index([roundId])
}
DeadlinePolicy
| Policy | Behavior |
|---|---|
HARD |
Submissions are cut off at closesAt. No uploads after the deadline. |
FLAG |
Submissions after closesAt are accepted but marked as Late. Admin can see late status. |
GRACE |
A grace period (gracePeriodMinutes) after closesAt during which submissions are still accepted without penalty. After grace, behaves as HARD. |
enum DeadlinePolicy {
HARD
FLAG
GRACE
}
SubmissionFileRequirement
Each window defines required file slots:
model SubmissionFileRequirement {
id String @id @default(cuid())
submissionWindowId String
slotKey String // "executive_summary", "business_plan", "pitch_video"
label String // "Executive Summary"
description String? // guidance text for applicants
required Boolean @default(true)
maxFileSize Int @default(10485760) // 10MB default
acceptedTypes String[] // ["application/pdf", "video/mp4"]
sortOrder Int @default(0)
submissionWindow SubmissionWindow @relation(...)
@@unique([submissionWindowId, slotKey])
}
Multi-Round Document Visibility
| Actor | Current Round Docs | Previous Round Docs |
|---|---|---|
| Applicant | Can upload/edit until window closes | Read-only (view/download only) |
| Judge | Sees current round docs in review | Sees previous round docs (clearly separated in UI) |
| Admin | Full control (upload/remove/replace) | Full control (upload/remove/replace) |
| Mentor | Sees within mentor workspace | Sees within mentor workspace |
When a submission window closes or a round advances:
- Applicant's editing permissions for that window's docs are revoked
- Docs remain visible for download
- Judges in subsequent rounds can view all prior docs
RoundSubmissionVisibility
Controls which prior round docs are visible to judges:
model RoundSubmissionVisibility {
id String @id @default(cuid())
roundId String // the round where the judge is reviewing
visibleRoundId String // the round whose docs are visible
separateInUi Boolean @default(true) // show in separate section
round Round @relation("reviewingRound", ...)
visibleRound Round @relation("visibleRound", ...)
@@unique([roundId, visibleRoundId])
}
For example, Jury 2 (R5) would have visibility entries for R1 (Intake docs) and R4 (Semifinal docs), both with separateInUi: true.
Part 2: Mentoring Workspace
Purpose
Mentoring is NOT a judging stage. It's a collaboration layer for finalist teams who have requested mentoring. Mentors help teams polish their submissions before live finals.
Who Gets Mentoring
- Only finalist teams (or whatever stage admin configures) that have "requested mentor" enabled
- Mentor assignment works similarly to judge assignment (from a mentor pool)
- Each mentored team gets one assigned mentor
Workspace Features
The mentor-team workspace provides three capabilities:
1. Messaging / Chat
model MentorMessage {
id String @id @default(cuid())
projectId String // the mentored project
mentorId String // the assigned mentor
senderId String // who sent the message
senderRole MentorMessageRole
content String @db.Text
createdAt DateTime @default(now())
project Project @relation(...)
mentor User @relation("mentorMessages", ...)
sender User @relation("sentMentorMessages", ...)
@@index([projectId, mentorId])
}
enum MentorMessageRole {
MENTOR
APPLICANT
ADMIN
}
Messaging allows real-time communication between mentor and team. Admins can also send messages into the workspace.
2. File Upload
model MentorFile {
id String @id @default(cuid())
projectId String
mentorId String
uploadedById String
uploaderRole MentorMessageRole
fileName String
fileKey String // MinIO storage key
fileSize Int
mimeType String
description String?
// Promotion tracking
promotedToSlot String? // slotKey if promoted to official submission
promotedAt DateTime?
promotedById String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
project Project @relation(...)
comments MentorFileComment[]
@@index([projectId, mentorId])
}
Both mentor and team can upload files. Files are stored in MinIO and accessed via pre-signed URLs.
3. Threaded File Comments
model MentorFileComment {
id String @id @default(cuid())
fileId String
authorId String
authorRole MentorMessageRole
content String @db.Text
parentId String? // for threading
createdAt DateTime @default(now())
file MentorFile @relation(...)
author User @relation(...)
parent MentorFileComment? @relation("commentThread", ...)
replies MentorFileComment[] @relation("commentThread")
@@index([fileId])
}
Comments are threaded (parentId for replies). Each comment is tied to a specific file.
Privacy
All mentoring workspace content is private by default:
- Visible to: the assigned mentor, the team members, and admins
- NOT visible to: other teams, other mentors, judges, audience
File Promotion to Official Submission
A mentoring file can be "promoted" to become an official submission for a required document slot in the active submission round.
Example flow:
- Team uploads "Business Plan Draft v3.pdf" to mentor workspace
- Mentor reviews and approves
- Team (or admin) marks it as the official "Business Plan" submission for Round 2
- System creates a
SubmissionPromotionEventwith immutable provenance
model SubmissionPromotionEvent {
id String @id @default(cuid())
projectId String
roundId String
slotKey String // the doc slot being filled
sourceType PromotionSourceType
sourceFileId String // MentorFile.id or admin-uploaded file ID
promotedById String // who triggered the promotion
createdAt DateTime @default(now())
project Project @relation(...)
round Round @relation(...)
promotedBy User @relation(...)
@@index([projectId, roundId])
}
enum PromotionSourceType {
MENTOR_FILE // promoted from mentor workspace
ADMIN_REPLACEMENT // admin replaced the file directly
}
Promotion authority:
- Team lead: can promote their own mentor workspace files
- Admin: can promote any file or directly replace with admin-uploaded file
- Mentor: can promote IF admin enables this per competition (configurable)
Provenance: Every promotion records who promoted, when, from which source file, and the source type. This audit trail is immutable.
MentoringConfig (Round Type Configuration)
const MentoringConfig = z.object({
eligibility: z.enum(['FINALISTS_ONLY', 'SEMIFINALISTS_AND_ABOVE', 'CONFIGURABLE']),
requireMentorRequest: z.boolean().default(true), // team must opt-in
assignmentMethod: z.enum(['MANUAL', 'AI_SUGGESTED', 'AI_AUTO', 'ALGORITHM']),
workspaceFeatures: z.object({
messagingEnabled: z.boolean().default(true),
fileUploadEnabled: z.boolean().default(true),
fileCommentsEnabled: z.boolean().default(true),
}),
promotionTarget: z.string().optional(), // roundId where promoted files go
allowMentorPromotion: z.boolean().default(false), // can mentors promote files?
deadlinePolicy: z.nativeEnum(DeadlinePolicy).default('FLAG'),
})
Mentor Dashboard
Mentors have a dedicated dashboard showing:
- Assigned teams: list of all teams they're mentoring
- Per-team workspace: click through to messaging, file exchange, comments
- Deadline tracking: upcoming deadlines for the mentored teams
- Progress indicators: which teams have submitted their required docs, which are pending
- File review queue: files uploaded by teams that need mentor review
See 08-platform-integration-matrix.md for the full mentor page mapping.
Admin Document Controls
Admins have full control over documents across all rounds:
| Action | Scope | Audit |
|---|---|---|
| View any submission | All rounds, all projects | Read-only, no audit needed |
| Upload file for a project | Any round, any slot | Logged with sourceType: ADMIN_REPLACEMENT |
| Remove/replace a file | Any round, any slot | Logged with previous file reference |
| Lock a submission window early | Specific window | Logged |
| Extend a deadline | Specific window | Logged |
| Promote a mentor file | Any project's workspace | Creates SubmissionPromotionEvent |
Integration Points
- R1 (Intake): First
SubmissionWindowwith R1 document requirements - R4 (Semifinal Submission): Second
SubmissionWindowwith R2 requirements; R1 docs locked for applicants - R5 (Jury 2): Judges see R1 + R2 docs clearly separated via
RoundSubmissionVisibility - R6 (Mentoring): Mentor workspace active, file promotion targets the active submission window
- R7 (Live Finals): Jury 3 sees all submitted docs from all rounds
See 03-competition-flow.md for the complete round-by-round specification.