napi/CLAUDE.md

124 lines
4.0 KiB
Markdown

# 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)