diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 639a5b4..1432bb3 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -38,9 +38,10 @@ sincronizzano tra dispositivi tramite Supabase. ## Database - Schema v1.0 + M1 applicati al nuovo Supabase -- `public.giocatori_squadra`: 17 giocatori iniziali presenti; solo 2 hanno l'email - registrata (`email`, migration `m5_email_giocatori_squadra`, DD-018) — le altre 15 - arriveranno con una migration futura +- `public.giocatori_squadra`: rosa iniziale di 17 giocatori (migration `m5_email_giocatori_squadra`) + più quelli aggiunti da `/admin` a stagione in corso; da settembre 2026 tutti i giocatori + attivi hanno l'email registrata (colonna `email`, DD-018), impostabile da `/admin` senza + bisogno di una migration - `public.giocatori_squadra` è ora la source of truth della rosa letta dall'app (DD-015, 03/09/2026): «Aggiungi giocatore» e «Disattiva giocatore» della dashboard admin si riflettono su Squadra, Presenze, Pagelle, Badge e Scout. `src/lib/crapp-data.ts` resta @@ -84,7 +85,9 @@ Google» risponde e **nessuno entra nell'app**, né in dev né sulla preview di `develop`. Il passo 1 qui sotto va fatto prima di mandare questa versione in produzione. -Passaggi in ordine, nessuno dei quali è reversibile a metà: +Passaggi in ordine, nessuno dei quali è reversibile a metà. **Stato al 03/09/2026: fatti i +passaggi 1-3; il passaggio 4 è un processo continuo (7 dei 16 giocatori attivi hanno già +fatto il primo accesso); il passaggio 5 (M4) è stato applicato.** 1. **Provider Google in Supabase** — Google Cloud Console: consent screen _External_ (scope `email` e `profile`, non sensibili: nessuna verifica richiesta, e la modalità _Testing_ @@ -101,15 +104,21 @@ Passaggi in ordine, nessuno dei quali è reversibile a metà: produzione senza toccare il comportamento attuale. 3. **Primo admin**, dopo il primo login (l'ID esiste solo da quel momento): `INSERT INTO public.user_roles (user_id, role) SELECT id, 'admin' FROM auth.users WHERE email = '';` -4. **Collegamento dei 17 account**: ciascuno accede con Google e viene collegato in - automatico al proprio giocatore per email (DD-018, migration - `m5_email_giocatori_squadra`) — nessuna scelta manuale. Finché l'email di un giocatore - non è impostata (oggi solo 2 dei 17 la hanno), il suo accesso mostra un errore e va - sbloccato aggiungendo l'email con una nuova migration. Uno slot già collegato può essere - liberato solo da un admin. +4. **Collegamento degli account**: ciascuno accede con Google e viene collegato in + automatico al proprio giocatore per email (DD-018) — nessuna scelta manuale. Finché + l'email di un giocatore non è impostata, il suo accesso mostra un errore; da `/admin` si + imposta l'email di un giocatore (nuovo o esistente) senza bisogno di una migration. Da + settembre 2026 tutti i giocatori attivi hanno l'email registrata, ma il collegamento vero + e proprio (`auth_user_id`) avviene solo al primo login di ciascuno, quindi resta un + processo continuo che si ripete a ogni nuovo giocatore aggiunto a stagione in corso. Uno + slot già collegato può essere liberato solo da un admin. 5. **Solo a squadra collegata**: migration `m4_solo_autenticati`, che toglie al ruolo `anon` l'accesso alle tabelle v1.0. Da lì in poi i dati sono raggiungibili solo con una sessione; le route in `src/routes/api/public/` usano la service role e continuano a funzionare. + **Applicata in produzione il 03/09/2026** — non è più necessario aspettare che l'intera + rosa abbia già fatto login: il login era già l'unica via d'accesso lato app, quindi i + giocatori non ancora collegati non erano comunque impattati; M4 chiudeva solo un residuo + di accesso diretto al database bypassando l'app. Attenzione: dev e produzione condividono lo stesso progetto Supabase. Un account di prova che collega uno slot lo occupa anche in produzione, e va liberato da un admin. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e92195e..4b99148 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,7 +6,7 @@ qui: sta in [ROADMAP.md](ROADMAP.md). ## Versione attuale — agosto 2026 -### Autenticazione e dashboard amministratore (su `develop`, non ancora in produzione) +### Autenticazione e dashboard amministratore (in produzione) - Login con Google tramite Supabase Auth (DD-011). Al primo accesso l'account si collega a un giocatore di `giocatori_squadra`, e il collegamento non è più modificabile dal @@ -18,6 +18,10 @@ qui: sta in [ROADMAP.md](ROADMAP.md). di nomi in `crapp-data.ts` è stata eliminata, altrimenti bastava scegliere il nome giusto per amministrare. - Migration `m4_solo_autenticati`: toglie al ruolo `anon` l'accesso alle tabelle v1.0. + Applicata in produzione il 03/09/2026, dopo aver impostato l'email di tutta la rosa + attiva — il login era già l'unica via d'accesso lato app, quindi il collegamento dei + singoli account (che resta un processo continuo a ogni login) non era comunque + condizionato da questa migration. - Collegamento automatico al proprio giocatore per email (DD-018, migration `m5_email_giocatori_squadra`): niente più scelta manuale da un elenco, `/benvenuto` confronta l'email dell'account Google con `giocatori_squadra.email` e collega da solo. @@ -32,8 +36,6 @@ qui: sta in [ROADMAP.md](ROADMAP.md). in `giocatori_squadra`, come gli altri campi che gestisce solo l'admin (DD-016/DD-018). La dashboard mostra chi è già tesserato (badge sulla scheda, contatore in "Squadra") e un pannello per registrare numero e data una volta arrivata la tessera dal CSI. - **Da applicare solo a squadra collegata**, altrimenti chi non ha ancora fatto login vede - l'app vuota. - Profilo giocatore: da `/profilo` ognuno compila i propri dati anagrafici e carica documento, certificato medico e foto tessera con le relative scadenze ([modules/profilo-giocatore.md](modules/profilo-giocatore.md)). diff --git a/docs/DATABASE.md b/docs/DATABASE.md index 4f4462c..699ab33 100644 --- a/docs/DATABASE.md +++ b/docs/DATABASE.md @@ -9,7 +9,7 @@ non in questo file. | Tabella | Scopo | Note | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `giocatori_squadra` | Anagrafica operativa della squadra, con ID testuali (`g1`…`gN`), dati gestiti dagli admin (nome, cognome, numero, ruolo), collegamento all'account (`auth_user_id`) ed email registrata (`email`). | Introdotta dalla migration `m1_giocatori_squadra`, source of truth della rosa (DD-015): `useRosa()` e gli altri punti che elencano i giocatori la leggono tramite `useGiocatoriSquadra()` (client) o `leggiGiocatoriSquadra()` (server), filtrando `attivo`. `src/lib/crapp-data.ts` resta solo come seed storico e fallback (`rosaFallback()`) quando il database non risponde, e come sorgente della data di nascita (non ancora una colonna di questa tabella). Vedi DD-015 e DD-016. La colonna `email` (migration `m5_email_giocatori_squadra`) è la chiave del collegamento automatico account↔giocatore al primo accesso (DD-018): NULL finché non nota, oggi impostata solo per 2 dei 17 giocatori. Le colonne `numero_tessera`/`data_tessera` (migration `m8_tesseramento_csi`) tracciano chi è già tesserato al CSI; come `numero`/`ruolo` le scrive solo un admin, il trigger di M1/M5 le include tra i campi bloccati per chi reclama il proprio slot. | +| `giocatori_squadra` | Anagrafica operativa della squadra, con ID testuali (`g1`…`gN`), dati gestiti dagli admin (nome, cognome, numero, ruolo), collegamento all'account (`auth_user_id`) ed email registrata (`email`). | Introdotta dalla migration `m1_giocatori_squadra`, source of truth della rosa (DD-015): `useRosa()` e gli altri punti che elencano i giocatori la leggono tramite `useGiocatoriSquadra()` (client) o `leggiGiocatoriSquadra()` (server), filtrando `attivo`. `src/lib/crapp-data.ts` resta solo come seed storico e fallback (`rosaFallback()`) quando il database non risponde, e come sorgente della data di nascita (non ancora una colonna di questa tabella). Vedi DD-015 e DD-016. La colonna `email` (migration `m5_email_giocatori_squadra`, impostabile anche da `/admin`) è la chiave del collegamento automatico account↔giocatore al primo accesso (DD-018): NULL finché non nota, oggi impostata per tutta la rosa attiva. Le colonne `numero_tessera`/`data_tessera` (migration `m8_tesseramento_csi`) tracciano chi è già tesserato al CSI; come `numero`/`ruolo` le scrive solo un admin, il trigger di M1/M5 le include tra i campi bloccati per chi reclama il proprio slot. | | `giocatori` | Anagrafica giocatori con UUID. | Presente ma **non usata** dal codice attuale: la convergenza è rinviata (DD-012, DD-014). | | `profili_giocatore` | Dati personali, metadati del documento d'identità, certificato medico e path dei file, in relazione 1:1 con `giocatori_squadra`. | Creata dalla migration `m2_profili_giocatore` (DD-016). Letta da `src/lib/profili.ts`; le policy mostrano al giocatore solo il proprio profilo e all'admin tutti. I file non stanno qui: la tabella conserva i path nel bucket. | | `user_roles` | Ruoli applicativi (es. amministratore, giocatore). | Fonte dei permessi di amministrazione, letta da `src/lib/ruoli.ts` (DD-011). Il primo admin va inserito a mano; vedi [PROJECT_STATE.md](../PROJECT_STATE.md). | diff --git a/docs/DESIGN_DECISIONS.md b/docs/DESIGN_DECISIONS.md index dbd3c01..4844e5b 100644 --- a/docs/DESIGN_DECISIONS.md +++ b/docs/DESIGN_DECISIONS.md @@ -518,22 +518,21 @@ Restano fuori, e non cambiano: DD-016 regola 2 prevedeva che, al primo accesso, il giocatore scegliesse manualmente il proprio slot libero da un elenco (`/benvenuto`). In pratica ogni giocatore ha un'email nota (o presto nota), quindi far scegliere un nome da una lista è un passaggio superfluo e un rischio: un giocatore può selezionare per errore lo slot di un compagno, e nulla nel flusso lo impedisce a livello di prodotto. **Decisione** -Al primo accesso, `giocatori_squadra` viene interrogata per email (case-insensitive, tramite la nuova colonna `email`) invece di mostrare un elenco di slot liberi. Se l'email dell'account Google corrisponde a una riga libera, il collegamento avviene automaticamente. Se non corrisponde a nessuna riga (email non ancora nota, o nessun profilo per quella persona), l'utente vede solo un messaggio d'errore che invita a contattare un amministratore, con un pulsante per uscire e riprovare con un altro account — nessuna selezione manuale di ripiego. Le email sono popolate via migration (`m5_email_giocatori_squadra`), non tramite un'interfaccia amministrativa in questa iterazione. Il trigger `enforce_giocatori_squadra_update` (DD-016) viene esteso per richiedere anche la corrispondenza email, non solo lo slot libero: il vincolo resta nel database, non solo nella UI. +Al primo accesso, `giocatori_squadra` viene interrogata per email (case-insensitive, tramite la nuova colonna `email`) invece di mostrare un elenco di slot liberi. Se l'email dell'account Google corrisponde a una riga libera, il collegamento avviene automaticamente. Se non corrisponde a nessuna riga (email non ancora nota, o nessun profilo per quella persona), l'utente vede solo un messaggio d'errore che invita a contattare un amministratore, con un pulsante per uscire e riprovare con un altro account — nessuna selezione manuale di ripiego. Le email sono popolate via migration (`m5_email_giocatori_squadra`) per la rosa iniziale; un'interfaccia in `/admin` per impostarle su nuovi giocatori è arrivata poco dopo (vedi "Alternative scartate"). Il trigger `enforce_giocatori_squadra_update` (DD-016) viene esteso per richiedere anche la corrispondenza email, non solo lo slot libero: il vincolo resta nel database, non solo nella UI. **Alternative scartate** - Mantenere la selezione manuale come ripiego quando l'email non trova corrispondenza → scartata: vanificherebbe la garanzia "ognuno collega solo il proprio profilo" e reintrodurrebbe il rischio di scelta errata che questa decisione vuole eliminare. -- Un'interfaccia admin per scrivere l'email dei giocatori → rimandata: non necessaria finché le email arrivano da migration; si può aggiungere in futuro senza toccare questa decisione. +- Un'interfaccia admin per scrivere l'email dei giocatori → rimandata al momento della decisione, poi implementata nel form "Aggiungi giocatore" di `/admin` (`src/routes/admin.tsx`): serviva per collegare i giocatori aggiunti a metà stagione senza passare da una nuova migration ogni volta. **Conseguenze** -- Le righe senza email nota restano bloccate — nessuno può collegarle, nemmeno per errore — finché una migration futura non la imposta. Oggi solo 2 dei 17 giocatori hanno l'email registrata. +- Le righe senza email nota restano bloccate — nessuno può collegarle, nemmeno per errore — finché un admin non la imposta da `/admin` (o, per la rosa iniziale, una migration). Da settembre 2026 tutta la rosa attiva ha l'email registrata. - `slotLiberi` (funzione ed elenco "slot liberi" in `/benvenuto`) è stato rimosso: non aveva più chiamanti in produzione dopo il cambio. - Un utente che accede con l'account Google sbagliato resta bloccato su `/benvenuto` finché non esce e riprova con l'account giusto. **Riesame** -- Quando tutte le 17 email saranno note e verificate. - Se in futuro serve un'assistenza admin diretta dal flusso di login invece che da `/admin`. --- diff --git a/docs/TODO.md b/docs/TODO.md index 1ca3528..6a694b0 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -7,10 +7,11 @@ Solo il lavoro in corso o imminente. L'elenco completo delle funzionalità previ - Documentazione tecnica del progetto. - Autenticazione Google e dashboard amministratore: il codice è completo su `develop` e il - login è ora l'unica via d'accesso. Restano i passaggi di configurazione, in quest'ordine: - provider Google in Supabase (senza, nessuno entra), migration M2, primo admin in - `user_roles`, collegamento dei 17 account, e infine la migration M4 che chiude gli accessi - `anon`. Stato di dettaglio in [PROJECT_STATE.md](../PROJECT_STATE.md). + login è ora l'unica via d'accesso. La migration M4, che chiude gli accessi `anon` alle + tabelle v1.0, è stata applicata in produzione (03/09/2026). Resta il collegamento dei + singoli account: ogni giocatore si aggancia al proprio profilo al primo login (DD-018), un + processo continuo — vale anche per chi viene aggiunto a stagione in corso da `/admin`. + Stato di dettaglio in [PROJECT_STATE.md](../PROJECT_STATE.md). ## Prossimo