# napi — Retroalimentación Personalizada a Estudiantes ## ✅ Estado: PRODUCCIÓN — 2 grupos activos (2026-02-25) --- ## Contexto Proyecto minimalista para proporcionar retroalimentación personalizada a los estudiantes, cerrando el bucle profesor → alumno. El profesor (Fénix) mantiene ficheros `notas.md` por alumno con: - Tabla resumen de todas las prácticas (nota + estado) - Feedback detallado por práctica - Próximos pasos concretos Los alumnos acceden desde cualquier dispositivo con su navegador, sin instalar nada. **Sin backend. Sin base de datos. Sin framework. Sin CDN.** --- ## Grupos Activos | Grupo | URL | Alumnos | Datos local | Datos zzz | |:------|:----|:-------:|:------------|:----------| | **DDAW2** | `https://notas.qu3v3d0.tech` | 19 | `~/napi-data/` | `/var/www/napi/data/` | | **ASIR1** | `https://asir1.qu3v3d0.tech` | 21 | `~/napi-data2/` | `/var/www/napi2/data/` | --- ## Arquitectura ``` PROFESOR (aldebaran / anka4) SERVIDOR (zzz / qu3v3d0.tech) ──────────────────────────── ───────────────────────────── ~/napi-data/ ←── sshfs ──→ /var/www/napi/data/ (DDAW2, 19 alumnos) ~/napi-data2/ ←── sshfs ──→ /var/www/napi2/data/ (ASIR1, 21 alumnos) /var/www/napi[2]/ ├── viewer.html ├── marked.min.js └── twemoji.min.js Nginx + auth_pam → $remote_user → data/$remote_user/notas.md → viewer.html renderiza con marked.js ``` ### Stack | Componente | Tecnología | Dónde | |:-----------|:-----------|:------| | **Datos** | Ficheros `notas.md` (Markdown) | zzz | | **Transporte** | sshfs mounts persistentes (systemd) | aldebaran/anka4 → zzz | | **Servidor web** | Nginx (1 server block por grupo) | zzz | | **Autenticación** | `libnginx-mod-http-auth-pam` | zzz | | **Renderer** | `marked.min.js` + `twemoji.min.js` + `viewer.html` | zzz | | **Notificaciones DDAW2** | `nginx-user-config-watcher.sh` (v3) + XMPP | zzz | | **Notificaciones ASIR1** | `python-upload-watcher.sh` (v7) + XMPP | zzz | | **SSL** | Certificado wildcard `*.qu3v3d0.tech` | zzz | --- ## Alumnos ### DDAW2 (19) — usernames = nombre de pila ``` anas, carlos, carlosv, daniel, danieln, erick, evelin, gianfranco, giorgio, joel, jorge, josue, juanan, juanjesus, kasandra, marius, miguel, pablo, patrick ``` SFTP chroot: `/home/USER/html/` ### ASIR1 (21) — usernames = apellido en minúsculas ``` barja, barrios, cayo, contrera, duque, florea, gomes, izquierdo, jara, lillo, linares, macedo, martinez, munoz, olcina, ponce, posada, quiroz, reynoso, sierra, torrero ``` SFTP chroot: `/home/USER/python/` · Contraseñas: leet-speak (`a→4, e→3, i→1, o→0`) --- ## SSH / Conexión a zzz ```bash ssh fenix@qu3v3d0.tech # clave sin -i, fenix tiene sudo ``` --- ## Ficheros Clave ### En zzz | Ruta | Descripción | |:-----|:------------| | `/var/www/napi/` | App DDAW2 (viewer + marked + twemoji + data/) | | `/var/www/napi2/` | App ASIR1 (idem) | | `/etc/nginx/sites-enabled/napi` | Server block DDAW2 | | `/etc/nginx/sites-enabled/napi2` | Server block ASIR1 | | `/usr/local/bin/python-upload-watcher.sh` | Watcher ASIR1 (v7) | | `/usr/local/bin/nginx-user-config-watcher.sh` | Watcher DDAW2 (v3) | | `/usr/local/bin/xmpp-notify.py` | Bot XMPP one-shot | ### En aldebaran/anka4 | Ruta | Descripción | |:-----|:------------| | `~/napi-data/` | sshfs → DDAW2 data | | `~/napi-data2/` | sshfs → ASIR1 data | | `~/.config/systemd/user/home-fenix-napi\x2ddata.mount` | Mount DDAW2 | | `~/.config/systemd/user/home-fenix-napi\x2ddata2.mount` | Mount ASIR1 | --- ## Pendiente - [ ] Renovar certificado SSL wildcard cuando expire (generado 2026-02-04, válido 365 días)