ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
6학년 학생을 위한 수학 평가와 무관한 독립 교육 시뮬레이터, Arte Nuevo 연구소 제공
Simulador educativo independiente de evaluaciones de Matemática, estilo Pruebas Aprender, para estudiantes de 6.º año. Instituto Arte Nuevo.
교육TypeScript · PLpgSQLGitHub @NovaSystems32온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Simulador educativo independiente de evaluaciones de Matemática, con formato similar al de las
Pruebas Aprender, para estudiantes de 6.º año de la escuela secundaria de Argentina. Identidad
visual del Instituto Arte Nuevo (logo en public/images/logo-arte-nuevo.png, tokens de color en
src/app/globals.css).
Simulador educativo independiente del Instituto Arte Nuevo. No pertenece ni representa a organismos gubernamentales. Todas las actividades son originales.
Este proyecto es una versión completamente independiente de Simulador_Aprender (Instituto
Santiago Ramón y Cajal): mismo código, componentes, diseño y funcionalidades, pero con una base de
datos nueva y vacía, repositorio propio e identidad visual propia. No comparte datos, usuarios,
proyecto de Firebase ni proyecto de Neon con el original (que además usaba Supabase, no Firebase).
react-katex) para fórmulas matemáticas@react-pdf/renderer y exceljs para informes en PDF/ExcelLa autenticación y los datos viven en dos sistemas distintos:
uid de cada usuario es el único dato
que la app lee de Firebase.db/migrations/. perfiles.id guarda el mismo uid que el usuario en Firebase
Auth — una columna text (los uid de Firebase no tienen formato UUID), sin FK entre
sistemas (no es posible cruzando bases distintas).src/app/login/actions.ts) verifica el usuario/contraseña contra la API
REST de Firebase (src/lib/firebase/rest.ts) y cambia el token de corta duración por una
cookie de sesión de Firebase (src/lib/firebase/session.ts, httpOnly, hasta 14 días). El
middleware (src/proxy.ts) y src/lib/auth.ts verifican esa cookie contra el SDK de
administrador de Firebase (src/lib/firebase/admin.ts) en cada request.auth.uid() fuera de Supabase/Firebase, las políticas usan
current_setting('app.usuario_id', true) — una variable de sesión que src/lib/db/contexto.ts
fija con SET LOCAL en cada transacción, con el uid ya verificado. El rol de runtime
(app_runtime2, ver db/migrations/0002_rol_runtime.sql) está sujeto a esas políticas; el rol
administrador de Neon solo se usa para migraciones y el alta del primer admin.No hay trigger de alta de usuario entre sistemas: cuando un admin/docente crea un usuario, la app
primero lo crea en Firebase Auth y recién después inserta su perfil en Neon
(src/lib/db/usuarios.ts), revirtiendo el alta en Auth si el segundo paso falla.
Requisitos: Node.js 20+, una cuenta gratuita de Firebase (Google) y un proyecto en neon.tech.
npm install
https://tu-dominio/recuperar-contrasena/nueva-clave (en desarrollo,
http://localhost:3000/recuperar-contrasena/nueva-clave). Sin este paso, el enlace del correo
de "olvidé mi contraseña" lleva a una página genérica de Firebase en vez de la propia del
simulador.NEXT_PUBLIC_FIREBASE_API_KEY en .env.local..env.local:
project_id → FIREBASE_PROJECT_IDclient_email → FIREBASE_CLIENT_EMAILprivate_key → FIREBASE_PRIVATE_KEY (pegalo tal cual, con los \n literales)Copiá .env.example a .env.local (cp .env.example .env.local) antes de completar estos
valores.
Creá un proyecto nuevo en neon.tech.
Copiá el connection string del rol por defecto (el "owner" del proyecto) a
DATABASE_URL_ADMIN en .env.local.
Corré las migraciones (crean toda la estructura: tablas, enums, índices, funciones y políticas
RLS; cero INSERT de datos):
npm run db:migrate
En el panel de Neon, creá un segundo rol llamado app_runtime2 (Project → Roles → Add role).
Neon genera su propio connection string/contraseña: copialo a DATABASE_URL en .env.local
(este es el que usa la app en runtime, sujeto a RLS; nunca el del rol administrador).
Volvé a correr npm run db:migrate — 0002_rol_runtime.sql es idempotente y, ahora que el rol
existe, le otorga los permisos necesarios.
Con .env.local completo (Firebase + Neon):
npm run db:crear-admin
Pide el email y la contraseña por línea de comandos (no quedan escritos en ningún archivo), crea el
usuario en Firebase Auth y su perfil con rol admin en Neon. A partir de ahí, el resto de los
usuarios se crean desde el panel de administración de la propia aplicación.
npm run dev
Abrí http://localhost:3000.
Para producción:
npm run build
npm run start
npm test # corre una vez
npm run test:watch
Cubren la lógica de corrección automática (src/lib/scoring.ts), la selección aleatoria y el
armado de intentos (src/lib/randomization.ts), la generación/parseo de CSV y las reglas de
permisos por rol (src/lib/permisos.ts). Antes de dar por terminado un cambio, corré también:
npm run lint
npx tsc --noEmit
npm run build
db/
migrations/ DDL de Neon: tablas, enums, índices, funciones, RLS (sin datos)
scripts/
apply-migrations.mjs Aplica db/migrations/ contra DATABASE_URL_ADMIN
crear-primer-admin.mjs Alta manual del primer administrador (Auth + perfil en Neon)
src/
app/
login/ Inicio de sesión
estudiante/ Área del estudiante (rutas protegidas por rol)
docente/ Área docente (y admin, para banco/evaluaciones/reportes)
admin/ Administración (usuarios, cursos, configuración)
api/intentos/ Route handlers server-only: rendición y corrección de exámenes
api/reportes/ Exportación CSV/PDF/Excel
components/ Componentes de UI compartidos
lib/
db/ Capa de datos Neon (Drizzle): schema, contexto de sesión/RLS,
un módulo por dominio (cursos, preguntas, evaluaciones, intentos…)
firebase/ SDK de administrador, cookie de sesión y llamadas REST de Auth
scoring.ts Corrección automática (función pura)
randomization.ts Selección aleatoria y barajado (función pura)
intentos-server.ts Arma el snapshot de preguntas y corrige intentos (solo servidor)
permisos.ts Reglas de acceso por rol y ruta (función pura)
proxy.ts Protección de rutas por rol (runtime Node: el SDK de Firebase Admin
necesita módulos de Node, no funciona en el runtime Edge)
tests/unit/ Tests de Vitest
Las políticas RLS no pueden ocultar columnas específicas de una fila. Por eso, todo el flujo de
"rendir una evaluación" (iniciar intento, obtener preguntas, autoguardar respuestas, entregar y
corregir) pasa por Route Handlers (src/app/api/intentos/...) que leen la fila completa de
Neon (incluida respuesta_correcta) y arman manualmente la respuesta JSON, quitándola mientras el
intento está en_curso. El resto de la aplicación usa la misma capa de datos, siempre dentro de una
transacción con RLS activo para el usuario autenticado.
Administrador: usuarios, cursos, banco completo de preguntas, configuración general, todos los resultados.
Docente: banco de preguntas propio (y consulta de las preguntas activas de otros docentes), evaluaciones manuales o automáticas, asignación a cursos, incorporación de estudiantes, reportes (CSV/PDF/Excel) filtrados por curso/evaluación.
Estudiante: evaluaciones asignadas, rendición cronometrada con guardado automático, marcado de preguntas para revisar, resultados (cuando el/la docente los habilita), revisión de respuestas con resolución paso a paso, historial de intentos.
.env.local (ver arriba).npm run db:migrate (dos veces: antes y después de crear el rol app_runtime2 en Neon).npm run db:crear-admin para tener el primer usuario administrador.