# 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).

```prisma
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. |

```prisma
enum DeadlinePolicy {
  HARD
  FLAG
  GRACE
}
```

### SubmissionFileRequirement

Each window defines required file slots:

```prisma
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:

```prisma
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

```prisma
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

```prisma
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

```prisma
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:**
1. Team uploads "Business Plan Draft v3.pdf" to mentor workspace
2. Mentor reviews and approves
3. Team (or admin) marks it as the official "Business Plan" submission for Round 2
4. System creates a `SubmissionPromotionEvent` with immutable provenance

```prisma
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)

```typescript
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](./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 `SubmissionWindow` with R1 document requirements
- **R4 (Semifinal Submission)**: Second `SubmissionWindow` with 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](./03-competition-flow.md) for the complete round-by-round specification.
