Saltar al contenido principal

📖 Historias Técnicas Detalladas (MVP estricto)

Narradas paso a paso, con validaciones server-side y reglas del MVP actualizado. Notificaciones solo por email (Clerk); no hay notificaciones in-app.

🔗 Reglas transversales que aplican en todas las historias

  • Publicación manual: un hackathon solo se puede publicar si now >= registrationOpensAt; el cron no pasa de DRAFT a REGISTRATION, solo mueve estados ya publicados (REGISTRATIONRUNNINGJUDGINGFINISHED).
  • Roles exclusivos: un mismo usuario no puede ser JUDGE y participante del mismo hackathon. Organizer no asigna jueces que sean participantes activos ahí.
  • Equipos: crear/unirse/salir permitido solo si hackathon.status IN (REGISTRATION, RUNNING) y now < submissionDeadline. En JUDGING y FINISHED la membresía está congelada (solo lectura). Si el equipo no tiene submission y queda vacío, se borra inmediato; si tiene submission, no se permite que el último miembro salga.
  • Submissions: una por equipo (@@unique(teamId)); editable hasta submissionDeadline; después queda solo lectura. Segundo intento debe redirigir/avisar que ya existe submission del equipo.
  • Scores: un juez solo ve sus propios scores hasta FINISHED; después puede ver el detalle completo. Si un juez es removido, sus scores permanecen en DB pero se excluyen del cálculo (se cuentan solo jueces con HackathonJudge vigente; remover juez = hard delete de HackathonJudge en MVP).
  • Contacto sponsor: no se exponen emails; se envía correo vía proxy a los miembros del equipo cuando un sponsor contacta.

🎭 Historia 1: María (PARTICIPANT) vive todo el ciclo

Contexto: Primera vez en un hackathon; quiere formar equipo y competir.

Vistas y rutas clave: landing /, onboarding /onboarding, panel /dashboard, página pública del hackathon /hackathons/[slug], equipos /hackathons/[slug]/teams, mi equipo /hackathons/[slug]/my-team, submit /hackathons/[slug]/submit, leaderboard /hackathons/[slug]/leaderboard.

  • Día 1 (registro abierto): Llega a landing /, clic en “Registrarse” → Clerk → /onboarding. Completa perfil (nombre, bio, stack, avatar) → Profile creado con rol PARTICIPANT.
  • Ver hackathon: /hackathons/hackucentral-2025 muestra estado REGISTRATION y timeline. Botón “Registrarse”.
  • Registro: Clic en “Registrarse” → Server Action valida requireRole(['PARTICIPANT']), status=REGISTRATION, now dentro de ventana. Crea HackathonParticipation. Mensaje: “Registrado”. Redirige a /hackathons/hackucentral-2025/teams.
  • Equipo (crear): Tab “Crear equipo” en /hackathons/[slug]/teams: valida que no tenga equipo en ese hackathon, genera code único, crea Team y TeamMember. Muestra código para invitar. Tab “Unirse a equipo” acepta código y valida cupo, no pertenecer ya a otro equipo, y que el código exista. Crear/unirse permitido solo si hackathon.status IN (REGISTRATION, RUNNING) y now < submissionDeadline.
  • Invitar/Unirse: Sus compañeras usan el código; cada join valida participante registrado, cupo, unicidad de equipo. Listado muestra miembros actuales en /hackathons/[slug]/my-team.
  • Edición de equipo: Mientras hackathon.status IN (REGISTRATION, RUNNING) y now < submissionDeadline, botón “Salir del equipo” en /hackathons/[slug]/my-team. Si sale y el team no tiene submission, se borra su TeamMember; si queda vacío y no hay submission, se borra el equipo. Si el team tiene submission, no se permite que el último miembro salga.
  • Envío de proyecto (RUNNING): /hackathons/hackucentral-2025/submit muestra countdown. Server Action valida: miembro de equipo, status=RUNNING, now < submissionDeadline, tamaño de equipo >= minTeamSize, equipo sin submission previa, URLs válidas. Crea Submission (opcional challengeId). Si intenta un segundo envío, se redirige al detalle existente con mensaje “Tu equipo ya envió un proyecto”.
  • Edición de submission: Mientras now < submissionDeadline, botón “Editar” en /hackathons/[slug]/submit habilitado. Cambios en título/description/links/challenge. Al llegar la fecha límite, se bloquea y se muestra mensaje “Submission bloqueada (fecha límite superada)”.
  • Post-submission: Ve estado “En espera de evaluación”. Si intenta editar en JUDGING, recibe error de bloqueo.
  • Resultados (FINISHED): Recibe email “Resultados disponibles”. En /hackathons/[slug]/leaderboard ve ranking, puntaje ponderado, desglose por criterio y comentarios. Si ganó un challenge, lo ve destacado.

🎭 Historia 2: Carlos (JUDGE) evalúa sin sesgo

Contexto: Juez invitado; no puede participar en el mismo hackathon.

Vistas y rutas clave: panel de juez /judge, detalle del hackathon asignado /judge/hackathons/[slug], evaluación /judge/hackathons/[slug]/evaluate, vista de restricciones de scores /judge/hackathons/[slug]/all-scores, resultados post-evento /judge/hackathons/[slug]/results.

  • Rol y asignación: Admin cambia rol a JUDGE (email). Organizer asigna a Carlos en /admin/hackathons/[slug]/judges; validación bloquea si Carlos ya es participante. Se crea HackathonJudge; email de invitación. Un juez solo puede tener 1 hackathon activo (REGISTRATION/RUNNING/JUDGING) asignado.
  • Previo a judging: Panel de juez /judge y /judge/hackathons/[slug] muestra criterios (nombre, peso, maxScore) y la fecha de inicio de JUDGING con contador. No ve submissions antes de JUDGING.
  • Durante JUDGING: /judge/hackathons/[slug]/evaluate lista submissions del hackathon asignado, solo “Not evaluated” y “Evaluated por ti”. Al evaluar una submission, Server Action valida: rol JUDGE, asignación existe, hackathon JUDGING, submission pertenece al hackathon, scores dentro de rango. Crea Score por criterio con constraint (submission, judge, criterion) único.
  • Aislamiento: /judge/hackathons/[slug]/all-scores muestra mensaje de restricción; solo sus propias evaluaciones hasta FINISHED.
  • Progreso: Barra “Evaluated X/Y”, persistente. Puede salir y volver sin perder estado.
  • Después (FINISHED): En /judge/hackathons/[slug]/results ve leaderboard completo y comparativa de jueces. Si necesita corregir un score, solo ADMIN puede hacerlo (no hay edición de score por juez en MVP). Si se remueve al juez del hackathon, sus scores permanecen pero no se consideran en el cálculo (solo cuentan jueces con HackathonJudge vigente).

🎭 Historia 3: Patricia (ORGANIZER) publica y conduce el evento

Contexto: Organiza su primer hackathon.

Vistas y rutas clave: panel de organizador /admin/hackathons, creación /admin/hackathons/create, detalle y edición /admin/hackathons/[slug], criterios /admin/hackathons/[slug]/criteria, jueces /admin/hackathons/[slug]/judges, panel operativo /admin/hackathons/[slug]/dashboard.

  • Creación en borrador: Rol ORGANIZER. Formulario /admin/hackathons/create con validación de orden estricto: registrationOpensAt < registrationClosesAt < startsAt < submissionDeadline < judgingStartsAt < judgingEndsAt. Si el orden falla, se rechaza.
  • Criterios y jueces: Configura criterios (peso 1-10, maxScore) en /admin/hackathons/[slug]/criteria y asigna jueces en /admin/hackathons/[slug]/judges. No puede asignar jueces que sean participantes del mismo hackathon.
  • Publicación manual: Botón “Publicar” en /admin/hackathons/[slug] solo habilita si checklist completo y now >= registrationOpensAt. Al publicar pasa a REGISTRATION; cron seguirá moviendo estados en fechas programadas.
  • Gestión en marcha: /admin/hackathons/[slug]/dashboard muestra métricas (participantes, equipos, submissions). Puede remover participaciones o miembros de equipo problemáticos. Puede extender solo la fase siguiente, máximo +7 días, nunca acortar, y siempre preservando el orden de fechas. Si ajusta fechas, el cron usa los nuevos valores.
  • Visibilidad: No ve scores ni leaderboard durante JUDGING; solo progreso de evaluación (evaluadas X/Y). En FINISHED ve leaderboard completo.
  • Cierre: En FINISHED, exporta resultados y ganadores de challenges desde /admin/hackathons/[slug]/dashboard.

🎭 Historia 4: Roberto (SPONSOR) crea challenge y hace shortlist

Contexto: Sponsor de Google quiere promover Gemini API.

Vistas y rutas clave: panel sponsor /sponsor, creación de organización /sponsor/organizations/create, creación de sponsorship /sponsor/sponsorships/create, creación de challenge /sponsor/challenges/create, listado de submissions de su challenge /sponsor/challenges/[id]/submissions, shortlist /sponsor/shortlist.

  • Rol y organización: Rol SPONSOR. Crea Organization (logo, sitio, descripción) y queda como owner (OrganizationMember) en /sponsor/organizations/create.
  • Sponsorship y challenge: Crea Sponsorship ligado a un hackathon (tier, benefits JSON) en /sponsor/sponsorships/create. Luego crea Challenge asociado a esa sponsorship en /sponsor/challenges/create (título, descripción, tags, premios).
  • Durante el evento: Panel sponsor /sponsor y /sponsor/challenges/[id]/submissions lista submissions que eligieron su challenge (filtro challengeId). No ve scores ni feedback mientras status != FINISHED.
  • Shortlist: Puede marcar “Agregar a shortlist” en /sponsor/challenges/[id]/submissions; Server Action valida rol, membresía en la org, que la submission eligió su challenge, y unicidad submission+org. Guarda notas privadas. Consulta shortlist en /sponsor/shortlist.
  • Contacto: Botón “Contactar equipo” desde shortlist envía email vía proxy (Clerk) a los miembros; la UI no revela direcciones de correo.
  • Después (FINISHED): Ve leaderboard completo y ganador de su challenge (mejor score entre quienes eligieron su challenge) en /sponsor/challenges/[id]/submissions o /sponsor. Accede a perfiles detallados de shortlist para scouting.

🎭 Historia 5: Laura (ADMIN) “modo Dios” con override

Contexto: Admin de plataforma con poderes completos.

Vistas y rutas clave: panel admin /admin, gestión de usuarios /admin/users, listado de hackathons /admin/hackathons, edición forzada /admin/hackathons/[slug]/edit, ajustes de organizations /admin/organizations, sponsorships /admin/sponsorships, challenges /admin/challenges, resultados globales /admin/dashboard.

  • Usuarios: CRUD de usuarios en /admin/users, cambio de roles (incluido ADMIN). Puede borrar usuarios con cascade (participaciones, equipos, submissions, scores).
  • Hackathons: Edita cualquier campo en /admin/hackathons/[slug]/edit, incluso fuera de ventanas o rompiendo orden (override). Puede publicar sin restricciones de fecha (solo ADMIN), forzar estados y borrar hackathons completos.
  • Organizaciones y challenges: CRUD total sobre organizations, sponsorships, challenges en sus rutas /admin/organizations, /admin/sponsorships, /admin/challenges. Puede reasignar ownership.
  • Scores y submissions: Visibilidad total; puede corregir scores y submissions, y forzar estados/fechas si hay incidentes.
  • Auditoría futura: No hay audit log en el MVP; se asume confianza en ADMIN.

✅ Respuestas rápidas a las preguntas de coherencia

  1. Edición de submission: Sí, hasta submissionDeadline; después queda locked (aunque aún no inicie JUDGING).
  2. Conflicto de interés juez: MVP no incluye recusación por proyecto; la mitigación es preventiva (no asignar jueces que sean participantes). Si hay conflicto, Organizer/ADMIN puede remover al juez manualmente.
  3. Pausar/cancelar hackathon: No hay pausa/cancel en MVP. Organizer puede ajustar fechas futuras o ADMIN puede forzar estado/borrar el evento.
  4. Sponsor y resultados: Sponsor ve leaderboard final y ganador de su challenge cuando FINISHED; no ve scores ni emails antes.
  5. Notificaciones: Solo email (Clerk); no hay in-app notifications.

🔍 Checklist de coherencia

  • PARTICIPANT: Registro en ventana, equipo único por hackathon, leave hasta submissionDeadline, una submission por equipo, editable hasta el deadline, ve resultados en FINISHED.
  • JUDGE: Asignado solo si no es participante, evalúa con constraints por criterio, no ve scores ajenos hasta FINISHED.
  • ORGANIZER: Publica manualmente si now >= registrationOpensAt, mantiene orden de fechas, no ve scores hasta FINISHED, puede gestionar participantes/equipos.
  • SPONSOR: Ve solo submissions de su challenge, shortlist con notas, contacta vía proxy, ve ganador de su challenge en FINISHED.
  • ADMIN: Sin restricciones; puede override fechas, roles, scores y estados.