510d7ca4ec
Primo passo della separazione sito / piattaforme decisa da Adriano il 03/09: due applicazioni autosufficienti, senza workspace di root, cosi' che ognuna resti un progetto Astro completo ed estraibile. Qui non cambia niente del codice: solo la radice. I pattern del .gitignore che avevano una barra erano ancorati alla radice e dopo lo spostamento non avrebbero piu' coperto niente (data/*.db*, uploads/*): resi validi a qualunque profondita'. Suite: 45 file, 347 test verdi prima e dopo lo spostamento. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
111 lines
5.4 KiB
Markdown
111 lines
5.4 KiB
Markdown
# 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`. La pagina di login rimandava sempre a
|
||
`/admin`: ora usa `landingFor` sul ruolo dell'utente appena autenticato,
|
||
così ogni ruolo atterra su una pagina che può davvero aprire.
|
||
- 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). La catena prev/next segue l'ordine di navigazione
|
||
aree → capitoli → guide, non la numerazione dei capitoli: le aree li
|
||
raggruppano in un ordine diverso;
|
||
- `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.
|