4 Commits

Author SHA1 Message Date
Adriano Dal Pastro 13d8cdd137 Il sito lascia le piattaforme: separazione fusa in main
Fuso `feat/split-apps` (fermo dal 03/09 e mai portato in main, mentre il container
delle piattaforme girava gia' da li'): il sito e le piattaforme erano online in due
copie, con database diversi e ruoli divergenti — `nicola` era `admin` di la' e
`piattaforme` di qua, e la promozione di ieri valeva solo su una delle due.

Adesso `insanitylab.it/campus`, `/piattaforme` e `/login` fanno 404: le aree
riservate stanno solo su `piattaforme.tielogic.xyz`. Il pannello `/admin` resta.
Nel database del sito restano `admin` ed `editor`; `nicola` e `adriano` sono usciti.

Il lavoro di oggi e' passato intatto: edizione `settembre-2026` coi cinque
pacchetti, i 73 tag, il countdown al 19/09 e la correzione del sabato. Verificato
sull'immagine nuova prima di metterla, chiedendo la pagina a quattro date.

Tre cose che lo split del 03/09 aveva lasciato indietro, trovate eseguendo:

- **`Dockerfile` del sito copiava ancora `campus-content`**, spostato sotto
  `apps/platforms`: il build falliva. Nel sito non c'era piu' un solo riferimento a
  quella cartella - solo la riga del Dockerfile. Rimossa.
- **`migra-utenti.mjs --togli-dal-sito` era un no-op silenzioso**: il `continue`
  sugli utenti gia' presenti a destinazione saltava anche la cancellazione
  dall'origine. Siccome copiare e ripulire sono due passi separati apposta, l'opzione
  non funzionava proprio nel caso per cui esiste. Ora chi e' gia' di la' esce di qua
  lo stesso, e il riepilogo dice quanti ne ha tolti.
- **`.env` non e' in git**, quindi il merge non lo ha spostato sotto `apps/sito/`.
  L'`up` e' fallito dopo che il `down` aveva gia' tolto il container: **9,7 secondi
  di sito giu'**, misurati. La prova con `docker run` non lo aveva visto perche' non
  legge `env_file`. Il rimedio - `docker compose config` prima dello swap - e' scritto
  nel README del sito, che prima non diceva come si fa un deploy.

Sito 149 test verdi, piattaforme 202.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPKFABRT3y26dFNMquF3CS
2026-09-04 10:18:00 +00:00
AdrianoDev a59b4e0c0e crea-fascicolo: aprire il fascicolo di chi ha gia' un account
"Anche un admin deve avere il suo referto" (Adriano). Il codice lo permetteva
gia': il referto si aggancia all'utente, non al ruolo. Mancava il modo di
creare la riga che lega utente e fascicolo senza passare da seed-demo, che
inventa anche la persona e le risposte.

Non indovina niente: --sesso e' obbligatorio perche' entra nelle curve dei
punteggi, la data di nascita si puo' omettere e allora l'eta' resta vuota -
meglio un campo vuoto di una data plausibile e falsa. Si ferma se quell'utente
ha gia' un fascicolo: due fascicoli per la stessa persona sono due storie
parallele, e nessuna e' quella giusta.

Il fascicolo nasce vuoto: il referto dice "non hai ancora compilato il
questionario" finche' la persona non lo compila, che e' il percorso vero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
2026-09-03 13:02:54 +00:00
AdrianoDev 18b0877026 Longevity: il registro si semina da solo, e un cliente demo con un referto vero
seedRegistro/seedPesi esistevano dal 22/08 ed erano chiamati SOLO dai test: su
un database nuovo il registro restava vuoto, campiDelQuestionario non trovava
niente e la pagina del questionario si apriva SENZA DOMANDE. Non era un problema
della demo, era il primo avvio in produzione - lo stesso difetto gia' visto in
questo ramo (una funzione corretta che nessuno chiama), con la stessa
correzione: agganciarla dove non si puo' dimenticare, cioe' alla creazione del
database. Entrambe le semine sono INSERT OR REPLACE, quindi rilanciarle e' a
vuoto, e i punteggi gia' emessi non cambiano (sono congelati nella tabella
"score", che e' quello che il referto legge). Quattro test lo presidiano.

scripts/seed-demo.ts crea l'utente con ruolo "cliente", il fascicolo (passando
da creaCliente, l'unico varco fra identity e longevity) e compila il
questionario attraverso salvaDalForm - lo stesso percorso della pagina vera,
consenso compreso - cosi' i punteggi vengono calcolati e congelati come in
produzione. Si ferma se l'utente esiste gia': rifare la demo su dati esistenti
vuol dire duplicare o cancellare un fascicolo, e non e' una decisione da script.

Verificato girando l'app: Energy 74,5/100 con copertura 50%, Performance e
Recovery dichiarati insufficienti (5% e 35%) con l'elenco di cosa manca, Fitness
Age assente. E' la regola di Nicola all'opera - annullare invece di stimare - ed
e' lo stato vero del prodotto: nel registro ci sono solo le 20 domande del
questionario, i test fisici arrivano col gestionale trainer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
2026-09-03 12:27:48 +00:00
AdrianoDev 6301f521fd Separazione: le aree riservate diventano un'app propria (apps/platforms)
Campus, Stress Index e Longevity escono dal sito e diventano
apps.insanitylab.it, con utenti, sessioni, login e database propri.
Deciso da Adriano il 03/09/2026: una repo sola, due applicazioni
autosufficienti, cosi' che ognuna resti estraibile.

Misura che ha guidato il taglio: le tre aree condividevano col sito
SOLO l'identita' - ~170 righe fra auth.ts, middleware.ts e safe-next.ts.
Layout, librerie e dati erano gia' disgiunti.

Lato piattaforme:
- ruoli piattaforme/cliente/trainer/admin, senza quelli redazionali
- canAccessPath con default CHIUSO (nel sito era aperto: li' le rotte non
  elencate erano di chiunque fosse loggato, qui ogni sezione e' di qualcuno)
- tutta l'app protetta, si elencano le eccezioni invece dei prefissi protetti
- /api risponde 401/403, non un redirect verso una pagina di login
- tre database distinti: utenti, dati clinici senza nomi, mappatura coi nomi

Lato sito:
- ROLES tornano i tre redazionali; via le regole e il login pubblico
- il login del pannello RESPINGE un account emigrato invece di aprirgli una
  sessione: senza, landingFor lo mandava su /admin, il middleware glielo
  negava, e si formava un ciclo di redirect che sembra un guasto del sito
- l'header non mostra piu' un menu delle piattaforme: un link che esce

Verificato: sito 20 file / 146 test, piattaforme 26 file / 197 test, entrambi
i build passano, e l'app girata davvero in locale - il ruolo piattaforme entra
in Campus e viene rimbalzato da Longevity, il cliente il contrario.

Non ancora in produzione: manca il record DNS di apps.insanitylab.it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
2026-09-03 11:21:12 +00:00