diff --git a/.env.example b/.env.example index 6ada970..90fd36f 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ VITE_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_REPLACE_ME # Optional. Include the leading and trailing slash. -VITE_BASE_PATH=/tomatin-code-lab/beta/ +VITE_BASE_PATH=/tomatin-code-lab/ # Forces the static contribution sandbox and ignores Supabase credentials. VITE_FRONTEND_ONLY=false diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 8e518c9..3b568cc 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,84 +1,51 @@ name: Reportar un error -description: Informa un comportamiento incorrecto o una regresión reproducible. +description: Cuéntanos qué no funcionó. title: "[Bug]: " -labels: - - bug -assignees: - - eeminionn +labels: [bug] +assignees: [eeminionn] body: - - type: markdown - attributes: - value: | - Gracias por ayudar a mejorar Tomatin Code Lab. No incluyas tokens, contraseñas, soluciones privadas ni datos personales de estudiantes. - type: dropdown id: area attributes: - label: Área afectada + label: ¿Dónde ocurrió? options: - - Aula del estudiante - - Panel del mentor - - Misiones o evaluador - - Autenticación e invitaciones - - Sincronización con GitHub - - Accesibilidad o diseño responsive - - Documentación o infraestructura + - Vista del estudiante + - Panel del profesor + - Editor o ejecución de código + - Inicio de sesión + - Documentación + - Otro validations: required: true - type: textarea - id: summary + id: problem attributes: - label: Descripción - description: Explica qué ocurrió y cuál es el impacto. - placeholder: Al intentar..., la aplicación... + label: ¿Qué pasó? + placeholder: Explica el problema con tus palabras. validations: required: true - type: textarea - id: reproduction + id: steps attributes: - label: Pasos para reproducir - description: Incluye el recorrido mínimo y datos de ejemplo no sensibles. - placeholder: | - 1. Iniciar sesión como... - 2. Abrir... - 3. Presionar... + label: ¿Cómo podemos repetirlo? + placeholder: "1. Abrí...\n2. Presioné...\n3. Apareció..." validations: required: true - type: textarea id: expected attributes: - label: Resultado esperado + label: ¿Qué esperabas que ocurriera? validations: required: true - type: textarea - id: actual + id: evidence attributes: - label: Resultado actual y evidencia - description: Puedes arrastrar capturas o pegar errores ya redactados. - validations: - required: true - - type: input - id: environment - attributes: - label: Entorno - description: URL, navegador, sistema operativo y tamaño de pantalla. - placeholder: Beta, Safari 18, macOS, 1440 × 900 - validations: - required: true - - type: textarea - id: acceptance - attributes: - label: Criterios de aceptación sugeridos - description: ¿Qué debería comprobarse para cerrar este issue? - placeholder: | - - [ ] El recorrido termina sin errores. - - [ ] Existe una prueba de regresión. + label: Captura o información adicional + description: No incluyas contraseñas, tokens ni datos personales. - type: checkboxes - id: checks + id: privacy attributes: - label: Confirmaciones + label: Confirmación options: - - label: Busqué issues existentes y no encontré uno equivalente. - required: true - - label: Eliminé secretos y datos personales de la evidencia. + - label: Revisé que el reporte no contenga información privada. required: true - diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 9099567..b3108d7 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,74 +1,35 @@ name: Proponer una mejora -description: Propón una capacidad nueva a partir de una necesidad concreta. +description: Comparte una idea para hacer más útil o agradable la plataforma. title: "[Mejora]: " -labels: - - enhancement -assignees: - - eeminionn +labels: [enhancement] +assignees: [eeminionn] body: - - type: markdown - attributes: - value: | - Describe primero el problema. Una buena propuesta permite comparar alternativas antes de elegir una implementación. - type: dropdown id: audience attributes: - label: Persona beneficiada + label: ¿A quién ayuda? options: - - Estudiante - - Mentor o administrador - - Creador de contenido - - Contribuidor - - Varias de las anteriores + - Estudiantes + - Profesor + - Ambos + - Quienes contribuyen validations: required: true - type: textarea - id: problem + id: idea attributes: - label: Problema u oportunidad - description: Explica qué necesidad existe y cómo se resuelve actualmente. + label: Tu idea + placeholder: Describe qué te gustaría cambiar o agregar. validations: required: true - type: textarea - id: proposal - attributes: - label: Propuesta - description: Describe el resultado deseado sin asumir detalles técnicos innecesarios. - validations: - required: true - - type: textarea - id: alternatives - attributes: - label: Alternativas consideradas - description: Incluye opciones descartadas y sus principales compromisos. - - type: textarea - id: acceptance + id: reason attributes: - label: Criterios de aceptación - placeholder: | - - [ ] ... - - [ ] ... + label: ¿Por qué sería útil? validations: required: true - type: textarea - id: privacy + id: reference attributes: - label: Privacidad, seguridad y accesibilidad - description: Indica si toca datos estudiantiles, permisos, autenticación o interacción por teclado. - validations: - required: true - - type: textarea - id: references - attributes: - label: Referencias o diseños - description: Enlaces, capturas o productos de referencia. - - type: checkboxes - id: checks - attributes: - label: Confirmaciones - options: - - label: Busqué propuestas existentes y no encontré una equivalente. - required: true - - label: Entiendo que el proyecto está en desarrollo y la propuesta puede iterarse. - required: true - + label: Captura, dibujo o referencia + description: Opcional. diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml index 5e3ff64..5689c18 100644 --- a/.github/ISSUE_TEMPLATE/task.yml +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -1,59 +1,26 @@ -name: Registrar una tarea técnica -description: Define mantenimiento, documentación, deuda técnica o trabajo interno verificable. +name: Tarea del proyecto +description: Registra una tarea concreta de mantenimiento o documentación. title: "[Tarea]: " -labels: - - maintenance -assignees: - - eeminionn +labels: [maintenance] +assignees: [eeminionn] body: - - type: dropdown - id: area - attributes: - label: Área - options: - - Frontend - - Backend y Supabase - - Contenido de misiones - - Pruebas y accesibilidad - - GitHub Actions y despliegue - - Documentación y comunidad - validations: - required: true - type: textarea - id: context + id: goal attributes: - label: Contexto - description: Explica por qué la tarea existe y qué riesgo o costo evita. + label: Objetivo + placeholder: Explica brevemente qué debe quedar listo. validations: required: true - type: textarea id: work attributes: - label: Tareas - placeholder: | - - [ ] ... - - [ ] ... + label: Pasos + placeholder: "- [ ] Primer paso\n- [ ] Segundo paso" validations: required: true - type: textarea - id: acceptance + id: done attributes: - label: Criterios de aceptación - placeholder: | - - [ ] ... - - [ ] ... + label: ¿Cómo sabremos que está listo? validations: required: true - - type: textarea - id: validation - attributes: - label: Validación prevista - description: Comandos, recorridos o métricas que demostrarán que quedó terminado. - validations: - required: true - - type: textarea - id: rollout - attributes: - label: Despliegue y reversión - description: Completa esta sección cuando la tarea cambie producción, datos o permisos. - diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 729eda7..552a597 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,48 +1,18 @@ -## Issue relacionado +## Issue Closes # -## Qué cambia +## Qué cambié - +- Describe aquí el cambio. -- +## Cómo lo probé -## Por qué +- [ ] Ejecuté `pnpm check:frontend`. +- [ ] Revisé escritorio y móvil si cambié la interfaz. +- [ ] Agregué una captura o no aplica. - - -## Implementación - - - -## Evidencia visual - - - -## Validación - -- [ ] `pnpm check` -- [ ] `pnpm test:e2e` -- [ ] `supabase test db` o no aplica -- [ ] Probé el recorrido afectado en local o beta - -## Privacidad, seguridad y accesibilidad - -- [ ] No añadí secretos, soluciones privadas ni datos personales al código, fixtures o logs. -- [ ] Revisé RLS/permisos si cambié acceso a datos o autenticación. -- [ ] Revisé teclado, nombres accesibles, contraste y responsive si cambié la interfaz. -- [ ] Documenté cualquier riesgo residual. - -## Despliegue - - - -## Checklist de entrega - -- [ ] El PR tiene responsable, labels y milestone cuando corresponde. -- [ ] Actualicé pruebas y documentación. -- [ ] No contiene cambios ajenos al issue. -- [ ] CI está en verde. -- [ ] Está listo para revisión. +## Antes de enviar +- [ ] No incluí secretos, datos personales ni soluciones privadas. +- [ ] El PR contiene solo cambios relacionados con el issue. diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index b0430f4..b686874 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -33,7 +33,7 @@ jobs: node-version: 22 cache: pnpm - - name: Verify beta configuration + - name: Verify production configuration env: VITE_SUPABASE_URL: ${{ vars.VITE_SUPABASE_URL }} VITE_SUPABASE_PUBLISHABLE_KEY: ${{ vars.VITE_SUPABASE_PUBLISHABLE_KEY }} @@ -47,11 +47,11 @@ jobs: exit 1 } - - name: Build beta + - name: Build application env: VITE_SUPABASE_URL: ${{ vars.VITE_SUPABASE_URL }} VITE_SUPABASE_PUBLISHABLE_KEY: ${{ vars.VITE_SUPABASE_PUBLISHABLE_KEY }} - VITE_BASE_PATH: /${{ github.event.repository.name }}/beta/ + VITE_BASE_PATH: /${{ github.event.repository.name }}/ run: | pnpm install --frozen-lockfile pnpm build @@ -59,9 +59,8 @@ jobs: - name: Assemble static site run: | mkdir _site - cp index.html 404.html styles.css manifest.webmanifest robots.txt sitemap.xml sw.js .nojekyll _site/ - cp -R assets js _site/ - cp -R dist-beta _site/beta + cp -R dist-app/. _site/ + cp dist-app/index.html _site/404.html - name: Upload Pages artifact uses: actions/upload-pages-artifact@v4 @@ -82,25 +81,28 @@ jobs: id: deployment uses: actions/deploy-pages@v4 - - name: Smoke test beta + - name: Smoke test stable application env: PAGE_URL: ${{ steps.deployment.outputs.page_url }} REPOSITORY_NAME: ${{ github.event.repository.name }} run: | - beta_url="${PAGE_URL%/}/beta/" + root_url="${PAGE_URL%/}/" for attempt in {1..12}; do curl \ --fail \ --silent \ --show-error \ - --output beta.html \ - "$beta_url" - if grep -Fq "Tomatin Code Lab 3.0" beta.html \ - && grep -Fq "/$REPOSITORY_NAME/beta/assets/" beta.html; then - exit 0 + --output app.html \ + "$root_url" + if grep -Fq "Tomatin Code Lab" app.html \ + && grep -Fq "/$REPOSITORY_NAME/assets/" app.html; then + curl --fail --silent --show-error --output redirect.html "${root_url}beta/" + if grep -Fq "Redirigiendo a Tomatin Code Lab" redirect.html; then + exit 0 + fi fi echo "Waiting for GitHub Pages propagation ($attempt/12)." sleep 5 done - echo "::error::The deployed beta did not expose Tomatin Code Lab 3.0." + echo "::error::The stable Tomatin Code Lab application was not available at the root URL." exit 1 diff --git a/.github/workflows/supabase.yml b/.github/workflows/supabase.yml index 427e625..08cba4f 100644 --- a/.github/workflows/supabase.yml +++ b/.github/workflows/supabase.yml @@ -64,6 +64,9 @@ jobs: - name: Link project run: supabase link --project-ref "$PROJECT_ID" --password "$SUPABASE_DB_PASSWORD" + - name: Configure authentication URLs + run: supabase config push --project-ref "$PROJECT_ID" --yes + - name: Apply database migrations run: supabase db push diff --git a/.gitignore b/.gitignore index 1df4495..895b7d4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ coverage/ dist/ dist-beta/ +dist-app/ node_modules/ playwright-report/ test-results/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7faa446..0cd73c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,57 +1,41 @@ # Contribuir -Las contribuciones deben mantener el proyecto educativo, original, accesible y -seguro. Lee el [código de conducta](CODE_OF_CONDUCT.md) antes de participar. +Gracias por mejorar Tomatin Code Lab. La mayoría de las contribuciones están +pensadas para estudiantes y deben ser pequeñas, claras y fáciles de revisar. -## Issues +## Antes de empezar -Usa el formulario que corresponda y completa el contexto, las tareas, los -criterios de aceptación y la validación prevista. Cada issue de implementación -debe tener: +1. Revisa si ya existe un issue parecido. +2. Comenta que quieres trabajarlo o abre un issue breve. +3. Crea una rama desde `main`. -- Una persona responsable. -- Labels de tipo y área. -- Un milestone cuando forme parte de una entrega planificada. -- Un GitHub Project solo cuando exista un tablero activo que aporte seguimiento - adicional; no se crea uno para duplicar un milestone. -- Una checklist actualizada durante el trabajo. +Los forks pueden cambiar el frontend y su documentación. No deben modificar +`supabase/`, workflows de producción, secretos ni datos de estudiantes. -Las dudas abiertas pertenecen a Discussions. Nunca publiques secretos, tokens, -soluciones privadas ni datos personales de estudiantes. +## Trabajar en local -## Flujo local +```bash +corepack enable +pnpm install +pnpm frontend:dev +``` -Las contribuciones provenientes de forks son exclusivamente de frontend. Usa -`pnpm frontend:dev` para trabajar sobre la interfaz actual de Aula 3.0 sin -conectar Supabase. No cambies `supabase/`, secretos, migraciones ni workflows de -producción; CI rechazará esos archivos en un PR desde fork. +El modo local usa datos ficticios y no se conecta al backend. Antes de enviar: -1. Crea una rama enfocada desde `main`. -2. Realiza un cambio coherente y vinculado a un issue. -3. Ejecuta `pnpm check:frontend` y - `pnpm test:e2e:frontend`. -4. Abre un pull request con `Closes #…`, impacto, validación, privacidad y - despliegue. -5. Completa responsable, labels y milestone antes de solicitar revisión. -6. Fusiona solo con CI en verde y actualiza la checklist del issue. +```bash +pnpm check:frontend +``` -## Misiones +## Pull request -- Escribe enunciados originales; no copies tareas de otros cursos. -- Incluye objetivo, contrato, starter code, pistas progresivas y casos - ejecutables. -- Mantén las referencias locales acogedoras y comprensibles sin contexto - adicional. -- Prefiere un concepto claro antes que un chiste. +Incluye solamente: -## Privacidad +- El issue relacionado. +- Una explicación corta del cambio. +- Cómo lo probaste. +- Una captura si cambiaste algo visible. -Las credenciales, tests ocultos y entregas estudiantiles son datos de servidor. -No deben aparecer en el bundle, fixtures, logs ni historial de Git. El sandbox -de contribución no debe enviar solicitudes a Supabase, Judge0 ni GitHub. +GitHub Actions hará el resto de las comprobaciones. Nunca publiques tokens, +contraseñas, datos personales ni soluciones privadas. -## Accesibilidad - -Todos los controles necesitan una ruta de teclado y un nombre accesible. Revisa -escritorio y móvil, foco visible, movimiento reducido, contraste y etiquetas -largas en español. +Participa con respeto y sigue el [código de conducta](CODE_OF_CONDUCT.md). diff --git a/README.md b/README.md index f321d8f..2d5081e 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,72 @@ # Tomatin Code Lab -Tomatin Code Lab es un aula multilenguaje, todavía en desarrollo, para enseñar -y practicar Programación I y II mediante veinte misiones originales en -JavaScript, Python y C++. Reúne enunciado, editor, ejecución, feedback, -progreso y herramientas de mentor en una interfaz terminal. +Tomatin Code Lab es un aula para aprender programación resolviendo misiones, +recibir feedback y avanzar junto a un profesor. -- **Versión estable:** [eeminionn.github.io/tomatin-code-lab](https://eeminionn.github.io/tomatin-code-lab/) -- **Aula 3.0 beta:** [eeminionn.github.io/tomatin-code-lab/beta](https://eeminionn.github.io/tomatin-code-lab/beta/) -- **Estado:** en desarrollo; no es un producto terminado. +**Abrir la plataforma:** +[eeminionn.github.io/tomatin-code-lab](https://eeminionn.github.io/tomatin-code-lab/) -> Proyecto independiente. No está afiliado ni respaldado por MIT. Los -> enunciados y recursos educativos de esta plataforma son originales. +Los estudiantes trabajan desde el navegador, guardan su avance y entregan sus +respuestas. El profesor crea tareas, revisa entregas, acompaña el progreso y +administra el curso desde un panel propio. -## Contribuciones de frontend +## Contribuir al frontend -Los forks de este repositorio se usan exclusivamente para mejorar el frontend: -componentes, diseño, responsive, accesibilidad, redacción, navegación, -visualizaciones y experiencia de uso. No necesitas Supabase, OAuth, tokens, -base de datos ni acceso a la infraestructura oficial. +Las contribuciones de forks se concentran en la interfaz: diseño, textos, +accesibilidad, navegación, responsive y experiencia de uso. El modo local usa +datos de ejemplo y mantiene el backend desactivado, por lo que no necesitas +credenciales ni acceso a la clase real. -El sandbox carga el código actual de [`v2/`](v2/), la misma aplicación React y -TypeScript publicada como **Aula 3.0 beta**. No es una reconstrucción de la -versión estable antigua ni una maqueta distinta. +### Abrir el proyecto -## Abrir Aula 3.0 localmente - -Requisitos: [Git](https://git-scm.com/), Node.js 22 o superior y -[pnpm 11](https://pnpm.io/installation). - -1. Haz clic en **Fork** en GitHub. -2. Clona tu fork y registra el repositorio original como `upstream`: +Necesitas Git y Node.js 22 o superior. ```bash git clone https://github.com/TU_USUARIO/tomatin-code-lab.git cd tomatin-code-lab -git remote add upstream https://github.com/eeminionn/tomatin-code-lab.git -``` - -3. Instala dependencias: - -```bash corepack enable pnpm install -``` - -4. Construye y abre el sandbox estático: - -```bash -pnpm frontend -``` - -Se abrirá `http://127.0.0.1:4173/`. El comando genera HTML, CSS, JavaScript y -assets en `dist-beta/`, y luego los sirve con el preview estático de Vite. Ese -servidor solo entrega archivos: no implementa API, autenticación ni base de -datos. - -Para trabajar con recarga inmediata durante el diseño: - -```bash pnpm frontend:dev ``` -No abras `dist-beta/index.html` mediante `file://`: los módulos ES, Web Workers -y assets de Monaco necesitan un origen HTTP local. Esto no activa un backend; -solo evita las restricciones de seguridad que el navegador aplica a archivos -abiertos directamente desde el disco. - -## Qué funciona en el sandbox - -- Las vistas reales de estudiante y mentor de Aula 3.0. -- Navegación, filtros, pestañas, modales, responsive y vista estudiante. -- Las veinte misiones y sus variantes JavaScript, Python y C++. -- Monaco Editor, edición de código y borradores locales. -- Ejecución de JavaScript en Web Worker. -- Ejecución de Python en Pyodide Worker. -- Redimensionado del workspace, resultados y estados visuales. -- Personalización visual del avatar antes de guardar. -- Datos ficticios de diez estudiantes para diseñar dashboards y rankings. - -## Qué queda desactivado - -- Inicio de sesión real con GitHub. -- Lectura o escritura en Supabase. -- Entregas, tests ocultos y sincronización de resoluciones. -- Ejecución remota de C++ y cualquier llamada a Judge0. -- Crear o modificar tareas, invitaciones y misiones. -- Aprobar entregas, asignar XP o solicitar cambios. -- Guardar perfiles, eliminar feedback o modificar datos del curso. -- Edge Functions, Realtime y repositorios privados. - -Los controles siguen visibles para poder diseñar todos sus estados, pero las -acciones que necesitan backend aparecen deshabilitadas. Además, el runtime -ignora las credenciales Supabase aunque exista un `.env.local` por accidente. -Una barra amarilla persistente identifica el sandbox. - -## Archivos permitidos - -Una contribución desde un fork debe concentrarse en: - -- `v2/src/components/` -- `v2/src/pages/` -- `v2/src/styles.css` -- `v2/src/lib/` -- `v2/src/data/` cuando el cambio sea exclusivamente de presentación -- `v2/e2e/` y `v2/tests/` -- `v2/public/` y assets visuales -- `README.md`, `CONTRIBUTING.md`, `package.json` y `pnpm-lock.yaml` - -No modifiques desde un fork: - -- `supabase/` -- `.github/workflows/pages.yml` -- `.github/workflows/supabase.yml` -- secretos, migraciones, RLS, Edge Functions o sincronización de entregas - -CI revisa este límite. Un pull request proveniente de un fork que cambie -backend o workflows de producción fallará automáticamente. Los workflows de -Pages y Supabase también están restringidos al repositorio oficial. - -## Enviar un cambio - -1. Sincroniza tu fork y crea una rama: - -```bash -git fetch upstream -git switch main -git merge --ff-only upstream/main -git switch -c frontend/descripcion-corta -``` - -2. Trabaja usando `pnpm frontend:dev`. -3. Verifica el resultado: +Abre [http://127.0.0.1:4173](http://127.0.0.1:4173). Verás las mismas pantallas +de estudiante y profesor que están publicadas, con diez estudiantes ficticios. +Los botones que necesitan el backend siguen visibles para poder diseñarlos, +pero no realizan cambios reales. -```bash -pnpm frontend:build -pnpm check:frontend -pnpm test:e2e:frontend -``` +### Qué puedes modificar -4. Sube la rama: +- Componentes, páginas, estilos, textos y recursos de `v2/`. +- Pruebas relacionadas con tu cambio. +- Documentación del frontend. -```bash -git push -u origin frontend/descripcion-corta -``` +No modifiques `supabase/`, secretos ni workflows de producción desde un fork. +GitHub Actions comprueba este límite automáticamente. -5. Abre un pull request hacia `eeminionn/tomatin-code-lab:main`, enlaza un - issue y explica el cambio observable. Para cambios visuales incluye una - captura de escritorio y otra móvil. +### Enviar un cambio -Revisa también [CONTRIBUTING.md](CONTRIBUTING.md), el -[código de conducta](CODE_OF_CONDUCT.md) y los issues abiertos. +1. Crea una rama y realiza un cambio enfocado. +2. Ejecuta `pnpm check:frontend`. +3. Abre un pull request, enlaza el issue y agrega una captura si cambiaste la + interfaz. -## Forks y `.gitignore` +La guía corta está en [CONTRIBUTING.md](CONTRIBUTING.md). También aplican el +[código de conducta](CODE_OF_CONDUCT.md) y la [política de seguridad](SECURITY.md). -Un fork copia el historial y todos los archivos versionados. No copia secrets, -variables de Actions, usuarios, datos de Supabase ni el repositorio privado de -resoluciones. +## Archivos locales -`.gitignore` no es una caja fuerte: evita agregar archivos locales nuevos, pero -no oculta archivos que ya estaban versionados. En este proyecto quedan fuera -`node_modules/`, builds, reportes, cobertura y todos los `.env*`, excepto -`.env.example`. Para el sandbox no debes crear ningún `.env`. +Un fork contiene todos los archivos versionados, pero no copia secretos, +variables de GitHub Actions, datos de Supabase ni entregas privadas. Los `.env`, +dependencias, builds y reportes locales están excluidos mediante `.gitignore`. -## Comandos +## Comandos útiles | Comando | Uso | | --- | --- | -| `pnpm frontend` | Construye y abre el sandbox estático | -| `pnpm frontend:dev` | Sandbox con recarga inmediata | -| `pnpm frontend:build` | Genera el frontend estático en `dist-beta/` | -| `pnpm check:frontend` | Tipos, unidades y build desconectado | -| `pnpm check` | Verificación integral reservada al repositorio oficial | -| `pnpm test:e2e:frontend` | Recorrido del sandbox sin backend | -| `pnpm test:e2e` | Recorridos completos de la aplicación demo | +| `pnpm frontend:dev` | Abre el frontend local con recarga automática | +| `pnpm check:frontend` | Revisa tipos, pruebas y build del frontend | +| `pnpm test:e2e:frontend` | Prueba que el modo local no use el backend | +| `pnpm check` | Ejecuta la verificación completa del repositorio oficial | ## Licencia diff --git a/SECURITY.md b/SECURITY.md index df88f3f..52da181 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,41 +1,25 @@ -# Security +# Seguridad -## Versiones publicadas +La plataforma publicada usa GitHub para iniciar sesión y Supabase para proteger +cuentas, tareas y progreso. El modo local de contribución usa datos ficticios y +no se conecta al backend. -La versión estable mantiene cuentas y progreso de demostración en -`localStorage`. Sus credenciales públicas no protegen datos reales. +## Datos y ejecución -La beta 2.0 funciona en dos modos: - -- Sin variables Supabase usa datos ficticios locales para recorrer la interfaz. -- Con Supabase usa OAuth o magic link, invitaciones de un uso, roles de servidor, - RLS y Edge Functions para ejecutar entregas. - -No ingreses datos personales o soluciones reales en el modo demo. - -## Ejecución de código - -- El navegador limita el código a 64 KB y la salida a 32 KB. -- JavaScript y Python se ejecutan en Web Workers para pruebas visibles. -- C++ y todas las entregas verificadas pasan por una Edge Function y Judge0. -- La Edge Function limita CPU a 2 segundos, pared a 5 segundos y memoria a - 128 MB. -- Los endpoints no aceptan tests enviados por el cliente. Resuelven la versión y - los tests ocultos desde el esquema privado. -- El límite inicial es de 20 ejecuciones remotas y 10 entregas por usuario/hora. - -La instancia pública de Judge0 sirve para el piloto y no ofrece un SLA. Para -clases con requisitos de disponibilidad se debe configurar una instancia -gestionada o propia mediante `JUDGE0_URL`. +- Los estudiantes solo pueden leer su propio progreso y sus entregas. +- Las soluciones, pruebas privadas y credenciales permanecen en el servidor. +- JavaScript y Python pueden ejecutarse localmente para obtener feedback rápido. +- C++ y las entregas verificadas pasan por un ejecutor remoto con límites de + tiempo, memoria, tamaño de código y frecuencia. ## Secretos -Nunca confirmes `.env`, service-role keys, access tokens, contraseñas de base de -datos ni claves de Judge0. La clave publicable de Supabase puede vivir en el -frontend; la seguridad depende de RLS, no de ocultarla. +Nunca confirmes `.env`, tokens, contraseñas, service-role keys ni claves del +ejecutor. La clave publicable de Supabase puede aparecer en el frontend; los +datos se protegen con políticas RLS. ## Reportar una vulnerabilidad -Abre un security advisory privado en el repositorio. Incluye versión, pasos de -reproducción, impacto y una prueba mínima. No publiques secretos ni datos -personales en issues. +Usa un +[security advisory privado](https://github.com/eeminionn/tomatin-code-lab/security/advisories/new). +No publiques secretos ni datos personales en un issue. diff --git a/docs/BETA_ROLLOUT.md b/docs/BETA_ROLLOUT.md deleted file mode 100644 index b084871..0000000 --- a/docs/BETA_ROLLOUT.md +++ /dev/null @@ -1,50 +0,0 @@ -# Lanzamiento beta 3.0 - -Tomatin Code Lab 3.0 permanece en -`https://eeminionn.github.io/tomatin-code-lab/beta/` durante el piloto. La -versión estable de la raíz no se reemplaza todavía. - -## Barreras automáticas - -- CI ejecuta las pruebas heredadas, TypeScript, Edge Functions, las 60 - soluciones de referencia, el build y los recorridos Playwright. -- pgTAP aplica todas las migraciones desde cero y verifica RLS, privacidad y - contratos de versión. -- GitHub Pages falla si faltan las variables públicas de Supabase. -- Supabase falla si faltan los secretos de despliegue o de sincronización con - el repositorio privado de resoluciones. -- El deploy comprueba el acceso al issue de avisos. El secret de Actions - `NOTIFICATION_REPOSITORY_TOKEN` debe seleccionar únicamente - `eeminionn/tomatin-code-lab` y conceder `Issues: Read and write` junto con - `Metadata: Read-only`; el workflow lo copia como - `GITHUB_NOTIFICATION_TOKEN` a la Edge Function sin exponerlo. El nombre de - Actions evita el prefijo `GITHUB_`, reservado por GitHub. -- Después de publicar, Pages comprueba que `/beta/` responda y sirva la versión - 3.0 desde la ruta correcta. - -## Piloto con dos estudiantes - -- [ ] Iniciar sesión con GitHub mediante dos invitaciones de un solo uso. -- [ ] Confirmar que cada cuenta recibe únicamente rol `student`. -- [ ] Abrir la Misión 01 en dos acciones y comprenderla sin revelar pistas. -- [ ] Guardar código distinto en JavaScript, Python y C++ sin perder borradores. -- [ ] Ejecutar al menos un caso correcto y uno incorrecto en cada lenguaje. -- [ ] Entregar una misión y comprobar que cada estudiante actualice únicamente - su carpeta dentro del repositorio privado central. -- [ ] Revisar desde `/admin`, comentar una línea y solicitar cambios. -- [ ] Confirmar que la reentrega usa la versión actual sin borrar el historial. -- [ ] Aprobar una entrega y comprobar que el XP se emita una sola vez. -- [ ] Entrar en `Ver como estudiante` y confirmar que todas las mutaciones estén - deshabilitadas. -- [ ] Validar la experiencia en notebook y una edición breve desde móvil. - -## Paso a diez estudiantes - -El piloto se amplía cuando ambos estudiantes completan el recorrido sin pérdida -de código, filtración de datos privados ni bloqueos del ejecutor. Durante la -primera clase se revisan el estado de Supabase, la cola de Judge0, los errores -de sincronización y el tiempo medio de revisión desde `/admin`. - -La raíz se promueve solo cuando los diez estudiantes pueden iniciar sesión, -trabajar y entregar, y eeminionn puede llegar a cualquier entrega en un máximo -de tres acciones. diff --git a/docs/RELEASE.md b/docs/RELEASE.md new file mode 100644 index 0000000..0f509db --- /dev/null +++ b/docs/RELEASE.md @@ -0,0 +1,23 @@ +# Publicación estable + +La aplicación vigente se publica en +`https://eeminionn.github.io/tomatin-code-lab/`. + +## Comprobaciones automáticas + +- CI revisa tipos, pruebas, soluciones de referencia y recorridos del navegador. +- pgTAP aplica las migraciones desde cero y verifica privacidad y permisos. +- GitHub Pages falla si faltan las variables públicas de Supabase. +- Supabase aplica migraciones, configuración de autenticación y Edge Functions. +- El despliegue comprueba que la raíz sirva la aplicación actual. + +## Comprobación de una clase + +1. Iniciar sesión con una invitación de estudiante. +2. Abrir, ejecutar y entregar una tarea en cada lenguaje permitido. +3. Confirmar que el borrador no se pierde al recargar. +4. Revisar la entrega, solicitar cambios y aprobarla desde el panel. +5. Confirmar el XP, feedback y repositorio privado de resoluciones. +6. Revisar una pantalla de notebook y otra de celular. + +`/beta/` se conserva únicamente como redirección para enlaces antiguos. diff --git a/docs/UX_AUDIT_AULA_3_3.md b/docs/UX_AUDIT.md similarity index 99% rename from docs/UX_AUDIT_AULA_3_3.md rename to docs/UX_AUDIT.md index 10173b9..469f539 100644 --- a/docs/UX_AUDIT_AULA_3_3.md +++ b/docs/UX_AUDIT.md @@ -1,4 +1,4 @@ -# Auditoría de interacción: Aula 3.3 +# Auditoría de interacción ## Objetivo diff --git a/index.html b/index.html index 8e341bd..5e298ca 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ @@ -53,7 +53,7 @@ "@context": "https://schema.org", "@type": "Course", "name": "Tomatin Code Lab", - "description": "Ruta original de Programacion I y II con veinte misiones autocorregibles.", + "description": "Aula para aprender programación resolviendo misiones junto a un profesor.", "inLanguage": "es-CL", "provider": { "@type": "Person", diff --git a/manifest.webmanifest b/manifest.webmanifest index 5b9215b..5988957 100644 --- a/manifest.webmanifest +++ b/manifest.webmanifest @@ -1,7 +1,7 @@ { "name": "Tomatin Code Lab", "short_name": "Tomatin Lab", - "description": "Misiones originales de Programacion I y II con humor chileno.", + "description": "Aula para aprender programación resolviendo misiones junto a un profesor.", "lang": "es-CL", "start_url": "./", "scope": "./", @@ -17,4 +17,3 @@ } ] } - diff --git a/package.json b/package.json index 7ae9f68..211a6f4 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "type": "module", - "description": "Aula multilenguaje para practicar Programacion I y II.", + "description": "Aula para aprender programación resolviendo misiones junto a un profesor.", "scripts": { "dev": "vite --config v2/vite.config.ts", "frontend": "pnpm frontend:build && VITE_FRONTEND_ONLY=true VITE_BASE_PATH=/ vite preview --config v2/vite.config.ts --host 127.0.0.1 --port 4173 --open /", diff --git a/supabase/config.toml b/supabase/config.toml index 8f5abac..c3db6ea 100644 --- a/supabase/config.toml +++ b/supabase/config.toml @@ -17,9 +17,11 @@ port = 54323 [auth] enabled = true -site_url = "http://localhost:5173/tomatin-code-lab/beta/" +site_url = "https://eeminionn.github.io/tomatin-code-lab/" additional_redirect_urls = [ - "http://localhost:5173/tomatin-code-lab/beta/", + "http://127.0.0.1:4173/tomatin-code-lab/", + "http://localhost:5173/tomatin-code-lab/", + "https://eeminionn.github.io/tomatin-code-lab/", "https://eeminionn.github.io/tomatin-code-lab/beta/" ] diff --git a/supabase/functions/notify-assignment/index.ts b/supabase/functions/notify-assignment/index.ts index dd4e3c9..3bf3018 100644 --- a/supabase/functions/notify-assignment/index.ts +++ b/supabase/functions/notify-assignment/index.ts @@ -5,7 +5,7 @@ const DEFAULT_GITHUB_OWNER = "eeminionn"; const DEFAULT_GITHUB_REPOSITORY = "tomatin-code-lab"; const DEFAULT_GITHUB_ISSUE_NUMBER = "59"; const DEFAULT_APP_BASE_URL = - "https://eeminionn.github.io/tomatin-code-lab/beta/#"; + "https://eeminionn.github.io/tomatin-code-lab/#"; type DeliveryStatus = "pending" | "sent" | "partial" | "failed"; @@ -97,7 +97,7 @@ function commentBody( assignmentUrl(slug, assignment.id) })`, "", - "Tomatin Code Lab Aula 3.1 beta está en desarrollo.", + "Tarea enviada desde Tomatin Code Lab.", ] .filter((line, index, lines) => line !== "" || lines[index - 1] !== "") .join("\n") diff --git a/v2/e2e/frontend-only.spec.ts b/v2/e2e/frontend-only.spec.ts index 507b267..51f2b81 100644 --- a/v2/e2e/frontend-only.spec.ts +++ b/v2/e2e/frontend-only.spec.ts @@ -27,7 +27,7 @@ test("frontend sandbox keeps the current student UI without backend calls", asyn const backendRequests = watchBackendRequests(page); await page.goto("./"); - await expect(page.getByText("Sandbox local de Aula 3.0")).toBeVisible(); + await expect(page.getByText("Sandbox local para contribuir")).toBeVisible(); await page.getByRole("button", { name: "Ver interfaz de estudiante" }).click(); await page.getByRole("button", { name: "Omitir", exact: true }).click(); await expect( diff --git a/v2/index.html b/v2/index.html index 5f513c7..3309fe6 100644 --- a/v2/index.html +++ b/v2/index.html @@ -5,12 +5,12 @@ - Tomatin Code Lab 3.0 + Tomatin Code Lab
diff --git a/v2/playwright.config.ts b/v2/playwright.config.ts index 11bd7fa..6227eb7 100644 --- a/v2/playwright.config.ts +++ b/v2/playwright.config.ts @@ -4,7 +4,7 @@ import { fileURLToPath, URL } from "node:url"; const frontendOnly = process.env.VITE_FRONTEND_ONLY === "true"; const serverUrl = frontendOnly ? "http://127.0.0.1:4173/" - : "http://127.0.0.1:4173/tomatin-code-lab/beta/"; + : "http://127.0.0.1:4173/tomatin-code-lab/"; export default defineConfig({ testDir: "./e2e", diff --git a/v2/public/beta/index.html b/v2/public/beta/index.html new file mode 100644 index 0000000..ab64874 --- /dev/null +++ b/v2/public/beta/index.html @@ -0,0 +1,15 @@ + + + + + + + Redirigiendo a Tomatin Code Lab + + + +

Abrir Tomatin Code Lab

+ + diff --git a/v2/public/manifest.webmanifest b/v2/public/manifest.webmanifest index 7d4d486..88eeb1a 100644 --- a/v2/public/manifest.webmanifest +++ b/v2/public/manifest.webmanifest @@ -1,7 +1,7 @@ { - "name": "Tomatin Code Lab 3.0", + "name": "Tomatin Code Lab", "short_name": "Tomatin Lab", - "description": "Aula multilenguaje para Programacion I y II.", + "description": "Aula para aprender programación resolviendo misiones junto a un profesor.", "start_url": "./#/", "display": "standalone", "background_color": "#040906", diff --git a/v2/public/robots.txt b/v2/public/robots.txt new file mode 100644 index 0000000..f70398c --- /dev/null +++ b/v2/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://eeminionn.github.io/tomatin-code-lab/sitemap.xml diff --git a/v2/public/sitemap.xml b/v2/public/sitemap.xml new file mode 100644 index 0000000..d7935ea --- /dev/null +++ b/v2/public/sitemap.xml @@ -0,0 +1,8 @@ + + + + https://eeminionn.github.io/tomatin-code-lab/ + weekly + 1.0 + + diff --git a/v2/src/components/AppShell.tsx b/v2/src/components/AppShell.tsx index e18a181..717aafe 100644 --- a/v2/src/components/AppShell.tsx +++ b/v2/src/components/AppShell.tsx @@ -107,7 +107,7 @@ export function AppShell() { T_ Tomatin - CODE LAB 3.0 + CODE LAB