Files
InsanityLab-web/docs/superpowers/specs/2026-07-25-campus-design.md
T
2026-07-25 15:25:21 +02:00

108 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sezione Campus — design
Data: 2026-07-25 · Branch: `feature/campus` · Stato: approvato (approccio A)
## Obiettivo
Integrare le guide di studio del corso Biohacking Campus (progetto esterno
`/data/Sorgenti/AI-OS/projects/personale/biohacking-campus`) come sezione
riservata del sito InsanityLab, visibile soltanto agli utenti autenticati con
un ruolo dedicato. Le pagine devono adottare lo stile grafico del sito
(font, colori, CSS globale), non quello del generatore statico originale.
## Requisiti
1. **Nuovo ruolo `campus`**: vede soltanto la sezione `/campus`; nessun
accesso al pannello admin. `admin` accede a tutto. `superuser` e `user`
non accedono alla sezione campus.
2. **Generazione contenuti**: uno script legge le guide sorgente
(`*.studio.md`) dal progetto biohacking-campus e produce i contenuti nel
repo del sito. Rigenerabile a ogni aggiornamento del corso.
3. **Gestione utenti**: la pagina `/admin/users` esistente deve permettere di
creare/assegnare il ruolo `campus`.
4. **Navigazione dedicata**: dentro `/campus` non compaiono Header e Footer
del sito; navigazione propria (sidebar aree/capitoli) più un solo
richiamo "← Torna alla home" verso `/`.
5. **Protezione totale**: pagine e immagini (assets slide) mai servite a
utenti non autorizzati.
## Architettura
### Ruoli e accessi (`src/lib/auth.ts`, `src/middleware.ts`)
- `Role = 'admin' | 'superuser' | 'user' | 'campus'`.
- `RULES` esteso: `/campus/*``['campus', 'admin']` (admin passa sempre già
oggi per short-circuit).
- Middleware: `/campus/*` diventa percorso protetto (oltre a `/admin`,
`/api/admin`). Non autenticato → redirect a `/admin/login`.
- `landingFor('campus')``/campus` (dopo il login l'utente campus atterra
direttamente sulla sezione).
- Il ruolo `campus` NON deve accedere ai percorsi comuni dei loggati del
pannello (blog admin, upload): `canAccessAdminPath` ritorna `false` per
`campus` su `/admin/*` e `/api/admin/*` non esplicitamente consentiti.
- `/admin/users`: aggiunta option `campus` nelle due select (nuovo utente,
cambio ruolo).
### Sync contenuti (`scripts/sync-campus.mjs`)
- Input: root del progetto biohacking-campus (arg CLI, default il path locale
di sviluppo).
- Porta la struttura dati del generatore Python (`CHAPTERS`, `AREAS`, regex
intestazioni) in JS. Legge i `*.studio.md` da `studio/`, `qa/`, `slide/`,
`accelerator/`, `lezioni-live/`, `speaker/`, `consulenze/`, `masterclass/`.
- Converte markdown → HTML con `marked` (nuova devDependency) e riscrive i
riferimenti alle immagini slide verso `/campus/assets/...`.
- Output in `campus-content/` (root repo, committato):
- `nav.json` — aree, capitoli, lezioni ordinate (slug, titolo, sottotitolo,
docente, prev/next);
- `pages/<slug>.html` — frammento HTML del corpo di ogni guida;
- `assets/` — immagini slide copiate (~37 MB, commit una tantum).
- Idempotente: rigenera tutto e rimuove i file orfani.
### Rendering (`src/pages/campus/`, `src/layouts/Campus.astro`)
- `Campus.astro`: usa `global.css` e i font del sito; nessun `Header`/`Footer`;
sidebar con aree/capitoli/lezioni (voce corrente evidenziata) e link
"← Torna alla home"; responsive con menu mobile.
- Route SSR (runtime, non prerender — servono i file in `campus-content/`):
- `/campus` — portale con le card delle aree (da `nav.json`);
- `/campus/[...slug]` — pagina area (indice capitoli) o pagina guida
(frammento HTML + breadcrumb + prev/next). Slug non trovato → 404.
- `/campus/assets/[...path]` — endpoint che serve le immagini da
`campus-content/assets/` (protetto dal middleware come tutto `/campus`);
path traversal rifiutato; `Content-Type` da estensione; cache privata.
- Lettura file a runtime da `CAMPUS_DIR` (env, default `./campus-content`),
con cache in memoria di `nav.json`.
### Deploy (`Dockerfile`)
- Lo stage runtime copia solo `dist` e `scripts`; si aggiunge
`COPY --from=build /app/campus-content ./campus-content`.
- `/app/data` e `/app/uploads` sono volumi: `campus-content/` resta fuori da
entrambi, dentro l'immagine. Nessuna modifica a `compose.yaml`.
## Error handling
- `campus-content/` assente (sync mai eseguito): `/campus` risponde 404 con
messaggio esplicito nei log; il resto del sito non è impattato.
- Slug o asset inesistente → 404. Path traversal su assets → 400.
- Sync: file `.studio.md` con intestazione non riconosciuta → warning e skip,
exit code ≠ 0 solo per errori I/O.
## Testing
- `tests/auth-campus.test.ts`: matrice ruoli × percorsi (`campus` su
`/campus` sì, su `/admin/content` no; `user` su `/campus` no; ecc.),
`landingFor`, `isRole('campus')`.
- `tests/sync-campus.test.ts`: parsing intestazioni (lezione, Q&A, slide,
accelerator, consulenza, masterclass, speaker), generazione nav e
frammenti su fixture minima, riscrittura path immagini.
- Verifica manuale: login con utente `campus` (vede solo campus), `user`
(non vede campus), navigazione sidebar, immagini slide, mobile.
## Fuori scope
- Nessun tracciamento progressi/completamento lezioni.
- Nessuna ricerca full-text.
- Nessuna migrazione automatica degli utenti esistenti al nuovo ruolo.