Per ogni convocato un − o un + su battuta, ricezione, attacco e muro, separato per set e
fuori dal punteggio (DD-053, migration m39: colonna scout_partite.valutazioni). Lo stato in
corso le salva in scout_live.stato; il CSV admin ha la tabella per set.
Nella pagina dello scout tolti il blocco avversario/campo, i tasti delle azioni e il
tabellone del punteggio; il titolo della sezione mostra cognome e numero del giocatore.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Stesso difetto dell'MVP: votato_nome lo scriveva il client. Riusa il trigger della m37.
Da applicare su Supabase con db push (non ancora fatto).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Lettura diretta di mvp_voti solo del votante e degli admin, conteggi dalla vista
mvp_voti_anonimi; trigger che riempie votato_nome dalla rosa; il voto chiude 24 ore dopo
l'apertura. Da applicare su Supabase con db push (non ancora fatto).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
voto_mvp_consentito() controlla partita, presenza (presente o ritardo) di votante e votato e
l'attesa di 2 ore dall'inizio. Da applicare su Supabase con db push (non ancora fatto).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Il giocatore può solo inserire il proprio voto: UPDATE e DELETE restano agli admin.
Da applicare su Supabase con db push (non ancora fatto).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Colonna facoltativa eventi_app.link_maps con CHECK che accetta solo URL https di
Google Maps. Campo nel form di /eventi (admin e allenatori), validazione con
linkMapsValido() e test. Le schede di partita, allenamento ed evento mostrano
«Apri su Google Maps» solo se il link c'è; card e notifiche non cambiano.
Documentazione: calendario.md, DATABASE.md, CHANGELOG.
La migration m34 non è ancora applicata in produzione: va fatto db push prima di
rilasciare questo codice, che legge la nuova colonna.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Fine della fase di prova: la funzione avvisa admin e allenatori attivi. Test
aggiornato (l'allenatore ora è tra i destinatari), DD-050, notifiche, allenatore,
DATABASE, CHANGELOG, ROADMAP e PROJECT_STATE allineati. m33 non ancora applicata
in produzione.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Migration m32: tipo presenza_modificata, funzione e trigger su risposte_presenze
che avvisano gli admin attivi se una risposta cambia a 0-6 ore da una partita o
un allenamento (push, email e centro notifiche). Gli allenatori non la ricevono
finché dura la prova. Applicata in produzione il 09/10/2026.
Test di integrazione e unitario; DD-050, notifiche, DATABASE, CHANGELOG,
ROADMAP e PROJECT_STATE aggiornati (slot g18 ora giocatore).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Ogni giorno, dalle 8:00 (Europe/Rome), un job pg_cron orario manda a chi compie
gli anni «Buon compleanno, <Nome>! 🎂» e a tutti gli altri membri attivi,
allenatori compresi, «Oggi è il compleanno di <Nome>» (con più compleanni lo
stesso giorno un solo messaggio a testa, nomi in ordine alfabetico). Solo
titolo, senza corpo né età. Canali: push, centro notifiche ed email.
- migration m31: tipi `compleanno` e `compleanno_auguri`, registro
`compleanni_notificati` (una sola volta per destinatario e giorno, anche se la
notifica viene eliminata), funzione `genera_avvisi_compleanno()` e job
`avvisi-compleanno`, trigger push esteso ai nuovi tipi. Non ancora applicata
in produzione.
- 29 febbraio non gestito: chi è nato quel giorno è avvisato solo negli anni
bisestili (limite noto, documentato).
- test: integrazione `notifiche-compleanno` (ora e ora legale, destinatari,
più compleanni, registro, coda push/email, 29 febbraio, job pianificato);
unit sui nuovi tipi e sul corpo vuoto del service worker.
- documentazione: DD-047, catalogo e testi delle notifiche, DATABASE, CHANGELOG,
ROADMAP, PROJECT_STATE.
Chiude la issue #11.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
La migration m30 riduce il job automatico alla sola fascia delle 24 ore:
il sollecito arriva una volta a chi non ha risposto o ha risposto «forse»,
anche per un evento creato a meno di 24 ore dall'inizio. Il pulsante
manuale «Sollecita» non cambia. I tipi sollecita_presenze_12h e _6h restano
ammessi per le notifiche già generate. Migration applicata in produzione.
Test di integrazione aggiornati; documentati DD-045, moduli notifiche,
presenze e allenatore, DATABASE, ROADMAP e changelog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Il Profilo non chiede più la foto tessera e la scheda admin non la mostra.
Il completamento diventa dati personali 34%, documento 33%, certificato 33%.
La migration m29 elimina la colonna profili_giocatore.foto_path; le 4 foto
già caricate sono state cancellate dal bucket profili-giocatore. Migration
applicata in produzione.
Test: pesi e sezioni di profili-core, rendering di CampiProfilo, colonna
rimossa sul database locale. Documentati DD-044, modulo profilo-giocatore,
DATABASE, ROADMAP e changelog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
La migration m28 toglie i due job pg_cron che generavano il promemoria
prima di ogni evento. Funzione, tipi, registro e notifiche già generate
restano. Migration applicata in produzione.
Nuovo test sui job non più pianificati; documentati DD-043, modulo
notifiche, DATABASE, ROADMAP, WORKER_EMAIL e changelog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
La migration m27 riduce il job automatico alla sola fascia delle 3 ore:
l'avviso arriva una volta a chi deve portare i palloni e a chi li deve
prendere. I tipi turno_palloni_12h e _6h restano ammessi per le notifiche
già generate e per la revoca. Migration applicata in produzione.
Test di integrazione aggiornati (nessun avviso a 4,5 e 9 ore); documentati
DD-042, moduli, DATABASE, ROADMAP, glossario e changelog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Promemoria con «oggi/domani», data, ora e luogo. Turno palloni a 12, 6 e 3 ore
per gli eventi con un incaricato confermato, con revoca una tantum se
l'incaricato cambia. Sollecito presenze a 24, 12 e 6 ore ai destinatari
dell'evento senza risposta o con «forse». Due job pg_cron ogni 15 minuti; push
dei tipi automatici dalla coda; nessuna email per il turno palloni.
Nuovo test di integrazione sui job veri del database; aggiornati i test di
promemoria, code push ed email.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
m25: giocatori_destinatari_evento() include solo i giocatori attivi, quindi
l'allenatore non riceve più i promemoria a 24 e 3 ore, per nessun tipo di
evento (fino alla m24 li riceveva sempre, DD-034). Riceve ancora i messaggi
dello staff.
Test: nuovo destinatari-notifiche.test.ts (14 controlli sulle route vere con un
servizio push finto: promemoria, messaggio dello staff, sondaggio, sollecito,
turno palloni, permessi di allenatore e giocatore) e aggiornato
permessi-allenatore. Documentazione: DD-039, tabella delle notifiche
dell'allenatore, catalogo e tabella dei test che lo verificano.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
m23: un registro (promemoria_eventi_generati) ricorda i promemoria a 24 e 3 ore
già generati, così eliminare la notifica non li fa rigenerare dal cron né
riaccodare la mail a ogni giro.
m24: la push dei promemoria, che nascono nel database, la manda il worker
mailer/ con lo stesso modulo dell'app (coda notifiche_push_coda, esiti, backoff,
iscrizioni scadute eliminate, push scartate oltre 3 ore). Il sondaggio
pre-partita scrive anche notifiche_utente (tipo sondaggio_cacche): compare
in-app e arriva per email. L'immagine del worker si costruisce dalla radice
del repository per includere src/lib/webpush.server.ts.
Test: 9 di integrazione per m23, 17 per la coda push, 6 per la route del
sondaggio, nuovi casi unitari sul worker; prova end-to-end con un servizio
push finto. Documentazione e catalogo delle notifiche aggiornati.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Migration m22: coda notifiche_email_coda, preferenze_utente, trigger che
accoda ogni notifica di notifiche_utente e tre funzioni RPC riservate
alla service role. Worker in mailer/ (bun + nodemailer, solo polling in
uscita) con backoff, tetto giornaliero e healthcheck. Interruttore
«Email» in Profilo → Opzioni, acceso di default. Test unit e di
integrazione; documentazione aggiornata (DD-036 accettata).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
L'allenatore è uno slot di giocatori_squadra con tipo = 'allenatore' (DD-034):
- M20 aggiunge il valore allenatore ad app_role, da solo perché Postgres non lascia
usare un valore di enum nella transazione che lo crea;
- M21 aggiunge la colonna tipo, rende numero nullabile solo per gli allenatori,
blocca tipo nel trigger sugli slot e lascia all'allenatore nome e cognome del
proprio slot; un trigger tiene allineato il ruolo in user_roles al collegamento;
- eventi_app scrivibile da admin e allenatori; presenze, cacche e voti chiusi
all'allenatore; i promemoria evento lo includono sempre.
Compatibile con la 0.9.2: senza allenatori registrati non cambia nulla. Già
applicata in produzione con supabase db push; g18 «Beta Tester» è allenatore.
Il test permessi-allenatore verifica le regole contro il database locale.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Prima veniva mostrata solo per i 17 giocatori del seed storico: chi la
inseriva da sé restava con "Invalid Date" in Squadra, perché il dato
finiva solo in profili_giocatore (privato). Un trigger ora lo sincronizza
in giocatori_squadra.nascita, colonna pubblica a tutta la rosa.
Include il backfill dei profili già compilati prima di M18 (M19),
mancante nel push iniziale.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Icona a campana con badge delle non lette, indipendente dal canale push:
copre messaggio libero admin, promemoria evento (24h/3h prima), turno
palloni e sollecito presenze. Ogni notifica si rimuove con uno swipe o
la ×, non c'è pulizia automatica delle vecchie (DD-030).
Migration m17_notifiche_utente non ancora applicata in produzione.
Co-Authored-By: Claude Mythos <noreply@anthropic.com>
M15 ha ripulito una tantum le righe orfane con un blocco di DELETE
verificato solo a mano, senza lasciare nessuna rete di sicurezza
automatica per il futuro. Questa migration rende lo stesso corpo la
funzione bonifica_dati_evento_orfani(), riservata al service role, così
resta richiamabile se il trigger di M14 smettesse mai di funzionare.
Aggiunge test/integration/bonifica-evento.test.ts: inserisce una riga
orfana e una storica su id Scout/CSI, richiama la funzione via RPC e
verifica che tocchi solo la prima. Documenta l'aggiornamento in
DESIGN_DECISIONS.md (DD-029), DATABASE.md, test/README.md e CHANGELOG.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
M14 (DD-029) pulisce a cascata i dati collegati solo per le cancellazioni
future; questa migration ripulisce lo storico. Per risposte_presenze,
cacche_partita, turni_palloni, scout_sessioni, scout_live e scout_partite
elimina ogni riga il cui evento_id non esiste più in eventi_app.
Per mvp_voti, pagelle_voti e badge_social_voti serve più cautela: prima
del passaggio all'id evento CrAPP, match_id conteneva id Scout
(prefisso "s") o CSI (numerico o data-based), voti storici legittimi
mai collegati a un evento CrAPP. Il filtro si applica solo ai match_id
nel formato di nuovoIdEvento() ("e" + timestamp base36), così i vecchi
voti Scout/CSI restano intatti. Verificato manualmente sul database
locale prima dell'applicazione.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Un audit del modulo Obiettivi ha verificato che gli obiettivi non hanno
bisogno di pulizia: sono ricalcolati a runtime sull'elenco eventi
corrente. Il problema reale era un livello sotto: cancellare un evento
lasciava orfane le righe collegate in 8 tabelle (risposte_presenze,
cacche_partita, mvp_voti, pagelle_voti, badge_social_voti,
turni_palloni, scout_sessioni, scout_live, scout_partite), nessuna con
una foreign key verso eventi_app.
Aggiunge un trigger AFTER DELETE su eventi_app (migration
m14_pulizia_dati_evento_cancellato) invece di una FK con CASCADE, non
applicabile per dati storici disallineati (match_id che a volte punta
a id Scout/CSI). Verificato con un nuovo test di integrazione contro
il database locale; documentato in DESIGN_DECISIONS.md, DATABASE.md,
obiettivi-squadra.md, test/README.md e CHANGELOG.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Il badge Pagellone si sblocca ora solo con almeno 5 pagelle ricevute
(VOTI_MINIMI_PAGELLA): un voto solo poteva sbloccarlo o farlo sparire senza
significatività statistica. Aggiunto Giocatore.votiPagella per farlo funzionare.
La migration m13 (DD-027) estende le policy RLS di M11 su pagelle_voti, mvp_voti e
badge_social_voti: votante e votato devono essere convocati all'evento (prima solo
un filtro applicativo), e per le pagelle anche pagelle_chiuse=false. Le policy
admin restano permissive di proposito. Applicata anche al progetto cloud.
Copertura test completa: unit sulla soglia minima, integration sulle nuove policy
RLS (permessi.test.ts) e un end-to-end reale (pagella-badge.test.ts) sul modello
di mvp-badge.test.ts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rilettura completa della documentazione confrontata con il codice. Dove la doc
diceva il falso l'ho corretta; dove aveva ragione lei ho corretto il codice.
Autovoto (la doc aveva ragione)
- migration m12_niente_autovoto: vincoli mvp_no_autovoto e badge_social_no_autovoto,
gli stessi che pagelle_voti ha dalla v1.0. Le righe che li violano vengono
cancellate prima dell'ALTER, altrimenti fallisce; in locale non ce n'erano.
M11 garantisce solo che il voto sia firmato con il proprio votante_id, non che il
votato sia un altro: eleggersi MVP restava a un POST di distanza.
- VotazioneMvp non mostra più il votante nell'elenco, come già faceva VotoSocial.
Test che guardavano la colonna sbagliata
- scritture.test.ts verificava che aggiornato_il si muovesse, chiamandolo "quello che
alimenta la serie di conferme". È l'opposto: la serie usa risposto_il, che il trigger
di M9 deve tenere fermo. Ora il test prova a riscriverlo e controlla che il database
abbia tenuto la prima risposta; prima passava anche senza trigger.
- destinatariSollecito() esce dalla route sollecita-presenze e diventa una funzione pura
in presenze.ts, con i suoi test — stesso trattamento di avvisiPalloniEvento.
Tre riletture in meno
- giocatori-squadra, scout-store e avatar-store usavano invalidateQueries dove il dato
scritto era già noto: ora setQueryData, come il resto dell'app. Resta scout-live, dove
il lock può averlo vinto un altro dispositivo.
Documentazione riallineata
- presenze.md, badge.md, mvp.md: i limiti su RLS aperta e route non autenticata erano
superati da M11 e DD-024;
- serie-presenze.md: il filtro è e.data < oggi, non <=, e l'evento di oggi non conta
(conterebbe come assenza per tutti); aggiunta la tabella risposto_il/aggiornato_il;
- ARCHITECTURE.md ed EFFICIENZA_CLOUD.md: una sola eccezione a setQueryData;
- DATABASE.md: i vincoli delle tre tabelle di voto;
- PROJECT_STATE.md: fermo a M9, ora arriva a M12.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Le tabelle della v1.0 sono nate con policy USING (true) per anon e
authenticated. M4 ha tolto il GRANT ad anon e la cosa è passata per "ora è
chiuso", ma per gli autenticati non era rimasto nessun limite. Verificato sul
database locale con un utente appena creato, senza ruolo e senza slot nella
rosa: POST su eventi_app risponde 201, DELETE risponde 200. Qualsiasi giocatore
loggato poteva svuotare il calendario o riscrivere il voto di un altro parlando
direttamente con PostgREST, saltando l'interfaccia che quei pulsanti glieli
nasconde. Il permesso viveva solo nei componenti, cioè nel posto che un
attaccante non usa.
M11 fa dire alle policy quello che l'interfaccia già fa: eventi_app agli admin,
risposte_presenze e cacche_partita alla propria riga, i tre voti al proprio
votante_id. L'admin resta incluso ovunque, perché DD-017 gli riconosce già il
diritto di agire al posto del giocatore.
turni_palloni e le tabelle scout restano aperte di proposito: nell'interfaccia
non hanno nessun gate, quindi stringerle sarebbe una funzionalità nuova e non
una messa in sicurezza. Un test lo fissa, così se il gate arriva qualcuno se ne
accorge.
L'identità è lo slot di giocatori_squadra collegato all'account, con lo stesso
EXISTS delle policy dei profili: mio_giocatore_id() di M2 era già stata rimossa
dalla migration di correzione e non va reintrodotta.
I cinque test nuovi in permessi.test.ts hanno ognuno il proprio controllo
positivo — l'admin crea l'evento, il giocatore salva la propria presenza —
perché un database che rifiuta tutto passerebbe qualsiasi test di sola
negazione. Provata con db reset da zero; non applicata in produzione.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I tre contatori (serieAllenamenti, seriePartite, serieConferme) e streak erano
zero fisso in useRosa(): la sezione Serie di presenze del profilo mostrava sempre
progresso nullo, i badge legati alla costanza erano impossibili da sbloccare e
l'obiettivo Continuita di squadra restava a 0/12.
serieConsecutiva() e serieConferme() (src/lib/presenze.ts) derivano le serie dagli
eventi passati e da risposte_presenze gia in cache, senza query aggiuntive.
Migration m9: nuova colonna risposto_il con l'istante della prima risposta, resa
immutabile da un trigger, confrontata con eventi_app.creato_il per le conferme
entro 24 ore. Serviva perche aggiornato_il registra l'ultima modifica, quindi chi
rispondeva subito e cambiava idea dopo risultava lento.
Corregge anche la barra di progresso, che misurava valore/prossimo e tornava
indietro a ogni traguardo raggiunto (2/3 = 67%, poi 3/6 = 50%).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Numero e data della tessera arrivano dal comitato dopo l'iscrizione, quindi
li scrive solo un admin (come numero/ruolo): estende il trigger di M1/M5,
aggiunge il pannello dedicato in /admin con badge e conteggio in dashboard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Due bug architetturali, entrambi con la stessa causa: dati che vivevano
solo in localStorage, quindi visibili a un solo dispositivo.
- Il blocco "chi sta scoutando" (scout-live.ts) non funzionava mai tra
telefoni diversi: due persone potevano prendere il controllo insieme
da dispositivi diversi, sovrascrivendosi a vicenda le azioni nel
salvataggio condiviso. Ora usa scout_sessioni, tabella già presente
nello schema ma mai collegata al codice.
- La partita scoutata finita (scout-store.ts) veniva salvata solo in
localStorage: "Punti/Ace/Muri squadra" e le presenze derivate dallo
scout esistevano solo sul telefono di chi aveva chiuso la partita.
Nuova tabella scout_partite archivia la partita completa (azioni
incluse) per tutta la squadra.
useScoutMatches() mantiene la stessa firma di prima (ScoutMatch[]), ora
alimentata da una query invece che da localStorage: nessuna modifica
necessaria nei punti che la leggono (squadra, classifica, home,
dettaglio partita, rosa). Rigenerati i tipi Supabase.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Le foto caricate in Profilo vivevano solo in localStorage: ogni giocatore
vedeva la propria foto solo sul proprio dispositivo, mai quella dei
compagni nella rosa (Squadra). Ora vengono caricate in un bucket
pubblico dedicato (avatar-giocatori, migration m6) e il componente
Avatar carica l'URL pubblico con fallback su numero/iniziali se assente
o non ancora caricata.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Al primo accesso l'app collega da sola l'account Google al giocatore
la cui email registrata coincide (case-insensitive), invece di far
scegliere il nome da un elenco. Senza corrispondenza compare solo un
messaggio d'errore con un pulsante per uscire e riprovare con un altro
account: nessuna scelta manuale di ripiego.
- Migration m5: colonna `email` su giocatori_squadra, seed per Ivan
Cacciari e Davide Grilli, trigger esteso per richiedere anche il
match email oltre allo slot libero.
- slotPerEmail() sostituisce slotLiberi() (rimossa, senza più
chiamanti in produzione).
Co-Authored-By: Claude Mythos <noreply@anthropic.com>
Remove the free player selection from /benvenuto: without a Supabase session
no screen renders, and the VITE_AUTH_OBBLIGATORIA bridge flag is gone.
Admin rights now come only from user_roles, so the hardcoded name list in
crapp-data.ts is deleted along with its tests.
Add migration m4_solo_autenticati, which revokes anon access to the v1.0
tables. Apply it only once the whole team has linked an account.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Checklist "Fine lavoro" di AGENTS.md per il lavoro dei due commit precedenti.
- DATABASE.md: profili_giocatore creata, user_roles come fonte dei permessi, e
la nuova sezione Storage per il bucket privato.
- ARCHITECTURE.md: autenticazione e ruoli tra i punti fermi, comandi dello stack
Supabase locale; gli stessi comandi in CLAUDE.md.
- CHANGELOG.md: la voce è marcata come presente su develop e non ancora in
produzione.
- PROJECT_STATE.md: i cinque passaggi per attivare login e dashboard in
produzione, in ordine, con il redirect URI di Google e la query per il primo
admin. Segnalato che dev e produzione condividono lo stesso database.
- TODO.md: la dashboard esce dal backlog; entra il profilo lato giocatore, senza
il quale la dashboard resterebbe senza dati.
- modules/profilo-giocatore.md: registrate due scelte fatte in corso d'opera —
solo Google al posto di "Google oppure Email", e "Visualizza profilo" come
scheda in linea invece di una schermata separata.
ROADMAP.md resta con la casella non spuntata: la funzionalità è su develop, non
ancora rilasciata.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Implementa la voce "Dashboard amministratore" della roadmap v1.1, come descritta
in docs/modules/profilo-giocatore.md, insieme alla parte di profilo che la
alimenta.
- /admin: stato dei profili della squadra, download di documento, certificato e
foto tessera, export CSV con i 12 campi del tesseramento CSI. Un certificato
scaduto non conta come valido.
- Profilo giocatore: dati personali, documento (fronte e retro), certificato e
foto tessera, con widget di completamento in Home che sparisce al 100%.
- I permessi di amministrazione arrivano da user_roles (DD-011) e non più dalla
lista di nomi in crapp-data.ts, che resta come ponte finché
VITE_AUTH_OBBLIGATORIA non viene acceso in produzione.
- Login Google via Supabase Auth: al primo accesso l'account si collega a uno
slot libero di giocatori_squadra, e il vincolo lo fa rispettare il trigger di
M1 (DD-016 regola 2).
Migration additive: M2 crea profili_giocatore, M3 il bucket privato
profili-giocatore. Nessuna tabella v1.0 viene toccata, quindi si possono
applicare senza cambiare il comportamento attuale dell'app.
supabase/config.toml e seed.sql configurano lo stack locale: serve perché il
progetto Supabase è uno solo, condiviso tra sviluppo e produzione.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>