feat(mentor-workspace): re-scope files from assignment to project for team-wide visibility

- MentorFile.projectId is the new access boundary; mentorAssignmentId stays
  as informational audit FK (nullable).
- uploadFile derives projectId from the assignment; getFiles takes projectId
  directly; deleteFile/addFileComment auth checks any mentor on the project
  OR a project team member.
- HMAC upload token now binds to projectId (in addition to assignmentId).
- promoteFile reads file.projectId directly (no more mentorAssignment null
  navigation).
- Removes 3 placeholder NOT_FOUND guards added in Task 4.
This commit is contained in:
Matt
2026-05-22 16:53:07 +02:00
parent a5ad11a1b5
commit 3a1eb149b6
9 changed files with 133 additions and 55 deletions

View File

@@ -17,7 +17,7 @@ import { FileText, Upload, CheckCircle2, ArrowUp } from 'lucide-react'
import { toast } from 'sonner'
interface FilePromotionPanelProps {
mentorAssignmentId: string
projectId: string
}
function formatFileSize(bytes: number): string {
@@ -28,14 +28,14 @@ function formatFileSize(bytes: number): string {
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
export function FilePromotionPanel({ mentorAssignmentId }: FilePromotionPanelProps) {
export function FilePromotionPanel({ projectId }: FilePromotionPanelProps) {
const [selectedSlot, setSelectedSlot] = useState<string>('')
const utils = trpc.useUtils()
const { data: workspaceFiles = [], isLoading: filesLoading } =
trpc.mentor.workspaceGetFiles.useQuery(
{ mentorAssignmentId },
{ enabled: !!mentorAssignmentId },
{ projectId },
{ enabled: !!projectId },
)
const promoteMutation = trpc.mentor.workspacePromoteFile.useMutation({