I riferimenti ai documenti in AGENTS.md erano rotti: una venticinquina di link nella forma docs/[README.md](http://README.md), che spezzavano il nome del file a meta e puntavano a domini inesistenti. Ora sono percorsi relativi verificati, con CHANGELOG.md e DESIGN_DECISIONS.md sotto docs/ e PROJECT_STATE.md in root. Tolte da AGENTS.md le sezioni Architettura, Documentazione e Struttura della documentazione: duplicavano ARCHITECTURE.md e docs/README.md con uno stack ormai parziale, contro la regola "ogni informazione ha una sola casa" che docs/README.md stesso impone. Aggiunti invece i comandi, bun e la guardia minimumReleaseAge: Codex e Cursor leggono solo AGENTS.md e non avevano modo di sapere come si verifica una modifica. Scritta la checklist "Fine lavoro" che CLAUDE.md citava senza che esistesse. Nuova regola: chi aggiunge o modifica una funzione scrive o aggiorna il test nello stesso lavoro, i test devono essere verdi e la doc del modulo va aggiornata se il comportamento cambia (DD-020). Serve perche con main come branch di lavoro non c'e piu un ambiente di prova tra il codice e i giocatori. Il flusso git documentato non descriveva piu la realta: main e arrivato a 43 commit di vantaggio su develop, rimasto fermo. DD-003 e ora sostituita da DD-019: il branch dei commit lo decide l'utente, l'assistente al massimo consiglia un branch dedicato e non committa, non pusha e non apre PR di propria iniziativa. Allineati di conseguenza ARCHITECTURE.md (sezione branch), README.md (flusso, install con bun, comandi di test e lint), ROADMAP.md e TODO.md (le voci spuntate sono in produzione, non su develop) e PROJECT_STATE.md (auth e profilo giocatore in produzione, 20 migration fino a M9, passaggi 1-3 e 5 fatti). Corretti poi sei disallineamenti tra documentazione e codice, ognuno verificato sul sorgente: - badge.md e obiettivi-squadra.md dicevano che le serie sono inerti e che serieAllenamenti e sempre 0, quindi badge e obiettivo "Continuita di squadra" non sbloccabili. Falso da7237e8f: presenze.ts:48 le calcola e rosa.ts:64-67 le attacca al Giocatore. Il limite che resta e un altro, ora scritto: risposto_il non e ricostruibile prima di m9, quindi sulle risposte vecchie serieConferme e un'approssimazione. - TODO.md e PROJECT_STATE.md davano il tracciamento tesseramento CSI come da fare, mentre ROADMAP, CHANGELOG e DATABASE lo davano per fatto. Lo e: admin.tsx:264-278 registra numero e data, :472 mostra Tesserato/Da tesserare, :676 il contatore. - collegamento-csi.md indicava il check di parsing in src/lib/csi-core.test.ts; sta in test/unit/csi-core.test.ts, in src/lib non esiste nessun .test.ts. - profilo-giocatore.md annunciava cinque aree del profilo e ne elencava sette. - "Segnala un bug" e "Suggerisci una nuova funzionalita" (profilo.tsx:259-276, commit72a9864) non erano documentati da nessuna parte, contro DD-002: ora stanno in profilo-giocatore.md e nel CHANGELOG. npm run test: 28/28 file ok. npm run lint: 12 problemi, identici a prima di questa modifica e tutti in src/, non toccato qui. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
30 KiB
Registro delle decisioni di progetto
Questo documento raccoglie le decisioni importanti prese nel corso della vita di CrAPP: scelte che hanno influito sulla direzione del prodotto, sull’organizzazione del lavoro o su come l’app si evolve nel tempo.
Non descrive come è fatto il codice. Per quello esistono ARCHITECTURE.md e DATABASE.md.
Serve a rispondere a domande del tipo:
- Perché abbiamo scelto così?
- Cosa avevamo escluso e perché?
- Quando conviene riaprire una decisione?
Indice
Accettate
| ID | Titolo |
|---|---|
| DD-001 | Indipendenza da Lovable |
| DD-002 | Sviluppo document-first |
| DD-004 | Ogni versione aggiunge, non riscrive |
| DD-005 | Mobile-first |
| DD-006 | AI solo se utile |
| DD-007 | Badge calcolati, non in DB |
| DD-008 | Gamification equa tra ruoli |
| DD-009 | CSI manuale v1.1, API v2.0 |
| DD-010 | Niente storico certificati v1 |
| DD-011 | Auth reale prima del profilo |
| DD-012 | Non migrare ID in v1.1 |
| DD-013 | Portabilità dello stack |
| DD-015 | Rosa da hardcoded a DB |
| DD-016 | Schema dati Profilo Giocatore v1.1 |
| DD-017 | L'admin scrive al posto del giocatore |
| DD-018 | Collegamento automatico per email |
| DD-019 | Il branch lo decide l'utente |
| DD-020 | Test obbligatori e verdi |
In valutazione
| ID | Titolo |
|---|---|
| DD-014 | Convergenza schema DB |
Sostituite
| ID | Titolo |
|---|---|
| DD-003 | Branch main / develop |
Come usare questo registro
Ogni decisione segue lo stesso schema:
| Campo | Significato |
|---|---|
| Data | Quando la decisione è stata presa o confermata |
| Stato | Accettata · In valutazione · Sostituita · Obsoleta |
| Contesto | Quale problema o opportunità avevamo di fronte |
| Decisione | Cosa abbiamo scelto di fare |
| Alternative scartate | Cosa non abbiamo fatto e perché |
| Conseguenze | Cosa comporta nel quotidiano (utenti, admin, sviluppo) |
| Riesame | Quando ha senso riconsiderarla |
Quando aggiungere una voce
- una scelta influisce su più moduli o su più release;
- escludiamo un’alternativa non ovvia;
- accettiamo un compromesso consapevole (debito, limitazione, ritardo);
- cambiamo una decisione precedente.
Quando non serve
- dettagli implementativi locali;
- scelte estetiche minori;
- bugfix o correzioni puntuali.
Come registrare una nuova decisione
Copiare _template-dd.md in fondo al documento, assegnare il primo ID
libero e aggiungerlo all'indice.
Decisioni accettate
DD-001 — CrAPP deve restare indipendente da Lovable
Data: luglio 2026
Stato: Accettata
Contesto
Il progetto nasce come prototipo su Lovable Cloud. Per crescere serve controllo su codice, deploy, database e costi.
Decisione
Spostare lo sviluppo su repository GitHub indipendente, con deploy su Vercel e database Supabase gestito dal team.
Alternative scartate
- Restare su Lovable come unica piattaforma → troppa dipendenza da un servizio esterno.
- Riscrivere tutto da zero → costo e rischio inutili; il prototipo funzionava già.
Conseguenze
- Maggiore libertà e responsabilità per il team.
- Restano tracce del passaggio (dipendenze, meta tag): vanno eliminate gradualmente, non in blocco.
- L’app deve poter girare anche fuori dall’ecosistema Lovable (vedi
PORTABILITA.md).
Riesame
Quando il progetto non userà più alcun componente Lovable.
DD-002 — Sviluppo document-first
Data: agosto 2026
Stato: Accettata
Contesto
Con più persone (e assistenti AI) che lavorano sul codice, serviva un modo per evitare funzionalità “inventate” al volo e incoerenze tra moduli.
Decisione
Ogni nuova funzionalità significativa viene prima progettata e documentata in docs/modules/, poi implementata. Il flusso ufficiale è: idea → progettazione → documentazione → database → codice → test → release.
Alternative scartate
- Documentare solo a posteriori → troppo spesso incompleto o assente.
- Affidarsi solo al codice come documentazione → illeggibile per chi non programma.
Conseguenze
- Rallenta leggermente l’avvio di nuove feature, ma riduce rework e discussioni infinite.
- I moduli v1.0 vanno retro-documentati quando possibile.
- Nessuna feature non documentata entra in produzione.
Riesame
Se il team diventa molto piccolo e la documentazione smette di essere consultata.
DD-003 — Due branch: main stabile, develop per il lavoro
Data: agosto 2026
Stato: Sostituita da DD-019 (settembre 2026)
Contesto
Serve separare ciò che i giocatori usano ogni giorno da ciò che è ancora in prova.
Decisione
main→ produzione, sempre funzionante, deploy automatico.develop→ sviluppo e preview, merge sumainsolo dopo test.
Alternative scartate
- Sviluppare direttamente su
main→ rischio di rotture in produzione. - Branch per ogni feature → eccessivo per la dimensione attuale del team.
Conseguenze
- Gli utenti in produzione non vedono lavori incompleti.
- Ogni release su
maindeve includere verifica delle funzionalità esistenti.
Riesame
Sostituita: nella pratica il lavoro è finito direttamente su main e develop è rimasto
indietro. Vedi DD-019.
DD-004 — Ogni versione aggiunge, non riscrive
Data: agosto 2026
Stato: Accettata
Contesto
CrAPP v1.0 è già usata dalla squadra per presenze, calendario, scout, badge e notifiche. Rischiare regressioni su moduli funzionanti vanifica la fiducia degli utenti.
Decisione
Le nuove versioni introducono funzionalità. Non si riscrive un modulo già operativo salvo richiesta esplicita e pianificata.
Alternative scartate
- Refactoring ampio “per pulire” insieme a ogni release → alto rischio, poco valore immediato per gli utenti.
Conseguenze
- Coesistono temporaneamente soluzioni vecchie e nuove (es. dati hardcoded accanto a tabelle database).
- Il debito tecnico va gestito con migration dedicate, non di nascosto.
Riesame
Quando un modulo diventa ingestibile o blocca una release importante.
DD-005 — Mobile-first, pochi click, pochi schermi
Data: origine progetto
Stato: Accettata
Contesto
I giocatori usano l’app soprattutto da smartphone, spesso in spogliatoio o in palestra, con poco tempo e poca pazienza.
Decisione
Interfaccia semplice, veloce, ottimizzata per telefono. Navigazione ridotta (barra inferiore). Ogni schermata deve avere uno scopo chiaro.
Alternative scartate
- Layout da desktop con menu complessi → scomodo in mobilità.
- App nativa iOS/Android → costi e tempi di pubblicazione non giustificati per una squadra amatoriale.
Conseguenze
- Funzionalità amministrative complesse vanno semplificate o suddivise con cura.
- La PWA è la forma giusta per questo pubblico.
Riesame
Se emergono esigenze desktop forti (es. gestione documenti massiva solo da PC).
DD-006 — Intelligenza artificiale solo se porta beneficio reale
Data: origine progetto
Stato: Accettata
Contesto
L’AI è attraente ma può complicare l’app, aumentare i costi e creare aspettative irrealistiche.
Decisione
Usare l’AI solo quando riduce lavoro agli admin o migliora concretamente l’esperienza dei giocatori. Non introdurla “perché si può”.
Alternative scartate
- AI ovunque (chatbot, suggerimenti automatici, analisi predittive) → fuori focus per una squadra amatoriale.
Conseguenze
- “AI Allenamenti” è in roadmap v1.2, non v1.1.
- Ogni proposta AI va valutata con la domanda: chi risparmia tempo e quanto?
Riesame
Quando l’AI diventa economica e affidabile per casi d’uso chiari (es. generazione allenamenti).
DD-007 — Badge calcolati dall’app, non salvati nel database
Data: origine progetto
Stato: Accettata
Contesto
I badge dipendono da statistiche già disponibili (presenze, MVP, cacche, ecc.). Salvare ogni badge sbloccato nel database aggiungerebbe complessità senza beneficio immediato.
Decisione
I badge vengono calcolati al volo dall’applicazione in base ai dati esistenti. Non esiste una tabella badge dedicata.
Alternative scartate
- Tabella
badge_sbloccaticon storico → utile in futuro per notifiche retroattive o audit, ma non necessaria ora.
Conseguenze
- Meno migration e meno sincronizzazione.
- Lo “sblocco” celebrativo usa cache locale per non ripetere animazioni.
- Un eventuale storico badge richiederà una nuova decisione.
Riesame
Se servono badge manuali assegnati dagli admin o storico immutabile.
DD-008 — Gamification equa tra ruoli
Data: origine progetto
Stato: Accettata
Contesto
In pallavolo i ruoli hanno statistiche diverse (un libero non segna punti d’attacco). Confrontare tutti sugli stessi numeri sarebbe ingiusto e scoraggiante.
Decisione
Le statistiche personali in profilo e squadra devono essere eque per tutti i ruoli. Dati tecnici di reparto (punti, ace, muri) restano nello Scout Live come informazione di squadra, non come leva competitiva individuale.
Alternative scartate
- Classifiche individuali basate su punti → penalizza libero, palleggiatore, centrale.
Conseguenze
- Badge e obiettivi usano presenze, MVP, pagelle, serie, cacche — metriche accessibili a tutti.
- Lo scout resta strumento tecnico, non gioco.
Riesame
Se la squadra chiede esplicitamente classifiche tecniche per ruolo.
DD-009 — Tesseramento CSI manuale in v1.1, integrazione API in v2.0
Data: agosto 2026
Stato: Accettata
Contesto
La v1.1 deve aiutare gli admin a raccogliere documenti e dati per il tesseramento CSI. Un collegamento automatico al sistema CSI è complesso e non urgente.
Decisione
- v1.1: profilo completo, dashboard admin, download documenti, export CSV con i campi richiesti dal CSI.
- v2.0: eventuale collegamento automatico a CSI (calendario, risultati, classifica ufficiale).
Alternative scartate
- Integrazione CSI già in v1.1 → scope troppo ampio, dipendenza da API esterne non controllate.
Conseguenze
- Gli admin guadagnano subito tempo (niente più Excel e chat per i documenti).
- L’export CSV deve essere affidabile e completo: è il deliverable chiave della v1.1.
Riesame
Quando il CSI mette a disposizione API stabili o quando il volume di tesseramenti giustifica l’automazione.
DD-010 — Profilo giocatore: niente storico certificati in v1
Data: agosto 2026
Stato: Accettata
Contesto
Il certificato medico va aggiornato ogni stagione. Tenere lo storico di tutte le versioni complica upload, storage e privacy.
Decisione
In v1 il giocatore può sovrascrivere certificato e data di scadenza. Lo storico delle versioni precedenti non viene conservato.
Alternative scartate
- Archivio certificati → utile per audit, rinviato a versioni future.
Conseguenze
- Implementazione più semplice e veloce.
- Gli admin vedono solo il certificato attuale.
- Va comunicato chiaramente ai giocatori che sostituire il file elimina quello precedente.
Riesame
Se il CSI o il regolamento interno richiedono conservazione storica.
DD-011 — Autenticazione reale prima del profilo amministrativo completo
Data: agosto 2026
Stato: Accettata
Contesto
Oggi l’app identifica l’utente con la selezione del giocatore da una lista, senza login. Documenti, certificati e dati personali richiedono sapere chi sta operando e impedire accessi non autorizzati.
Decisione
Prima di completare il modulo Profilo Giocatore (v1.1), introdurre login con Google o email tramite Supabase Auth — non tramite Lovable Auth. Dopo il login, il giocatore associa il proprio profilo squadra.
Alternative scartate
- Continuare solo con selezione da lista → inaccettabile per dati sensibili.
- Lovable Auth → crea dipendenza da piattaforma che stiamo abbandonando.
Conseguenze
- Tutti dovranno fare login almeno una volta.
- Gli admin useranno ruoli veri (
user_roles), non una lista di nomi hardcoded. - È prerequisito per dashboard admin e export CSI.
Riesame
Dopo il rollout auth, se emergono problemi di adozione (giocatori poco digitali).
DD-012 — Non migrare gli ID giocatore in v1.1
Data: agosto 2026
Stato: Accettata
Contesto
L’app usa identificativi semplici (g1, g2, …) collegati a presenze, voti, palloni e altre funzioni già in uso. Nel database esiste anche una tabella giocatori con UUID, non collegata al codice attuale.
Decisione
Per la v1.1 non unificare gli ID. I nuovi dati del profilo si agganciano agli identificativi già in uso. La migrazione verso UUID resta un lavoro separato, pianificato e testato.
Alternative scartate
- Migrare tutto a UUID in v1.1 → rischio alto di rompere presenze, voti, scout e notifiche.
Conseguenze
- Coesistono due modelli anagrafici fino a migration dedicata.
DATABASE.mdva tenuto aggiornato su cosa è “attivo” e cosa è “futuro”.
Riesame
Quando la v1.1 è stabile e c’è tempo per una migration con checklist regressioni completa.
DD-013 — Portabilità: l’app non deve dipendere da servizi esclusivi
Data: luglio 2026
Stato: Accettata
Contesto
La squadra potrebbe voler cambiare hosting, database o fornitore auth in futuro.
Decisione
CrAPP deve poter girare su Node.js + PostgreSQL standard. Niente funzionalità bloccate su servizi proprietari. I dati si accedono solo tramite moduli in src/lib/, non direttamente dai componenti.
Alternative scartate
- Accettare lock-in per velocità → contrario alla lunga vita del progetto.
Conseguenze
- Supabase va bene perché è PostgreSQL e self-hostable.
- Le API push e i job restano endpoint HTTP richiamabili da qualsiasi scheduler.
Riesame
Se si adotta un servizio che viola questa regola.
DD-016 — Schema dati Profilo Giocatore v1.1 (F0)
Data: agosto 2026
Stato: Accettata
Contesto
La progettazione F0 del modulo Profilo Giocatore ha definito come persistere dati personali, documenti e certificati, in coesistenza con l’anagrafica attuale (g1…g17 nel codice) e con la tabella giocatori UUID già presente ma non usata. Serviva una scelta chiara su dove salvare i dati, come collegare l’autenticazione e come proteggere documenti sensibili — senza toccare le tabelle v1.0 già operative.
Decisione
Per la v1.1 si introducono due nuove tabelle additive:
giocatori_squadra— anagrafica squadra con ID testuali (g1…g17), dati gestiti dagli admin (nome, cognome, numero, ruolo) e collegamento account (auth_user_id).profili_giocatore— dati personali, metadati documento identità, certificato medico e path dei file, in relazione 1:1 congiocatori_squadra.
Regole vincolanti:
giocatori_squadradiventa progressivamente la source of truth per l’anagrafica squadra. Durante la transizione,crapp-data.tsresta come fallback se il database non è disponibile o i dati non sono ancora migrati.- L’associazione
auth_user_id↔ giocatore è un’operazione controllata e atomica (es. al primo accesso da/benvenuto, conUPDATE … WHERE auth_user_id IS NULL). Il giocatore non può modificare liberamenteauth_user_id; solo un admin può resettarlo in casi eccezionali. - I file (documento identità, certificato, foto tessera) vivono nel bucket Storage
profili-giocatore, configurato come privato. - Documenti personali e sanitari non devono mai essere esposti tramite URL pubblici. Accesso solo tramite client autenticato con policy RLS, o signed URL a scadenza breve per download admin.
- Le tabelle v1.0 esistenti non vengono modificate (
eventi_app,risposte_presenze, voti, palloni, scout, push, ecc.). Il profilo si aggancia agli IDg1…g17già in uso, senza migrare verso UUID in v1.1 (coerente con DD-012). - La tabella
giocatori(UUID) resta invariata e non usata dal modulo profilo in v1.1.
Alternative scartate
- Estendere la tabella
giocatoriUUID → conflitto con ID operativi del codice e rischio di regressioni. - Salvare file come base64 nel database → ingestibile, difficile da gestire e da scaricare.
- Bucket pubblico con URL permanenti → inaccettabile per dati sanitari e documenti d’identità.
- Permettere al giocatore di cambiare
auth_user_idliberamente → rischio di impersonazione e race condition. - Modificare tabelle v1.0 per aggiungere FK verso il profilo → viola DD-004 e DD-012.
Conseguenze
- Coesistono temporaneamente tre rappresentazioni dell’anagrafica:
crapp-data.ts(fallback),giocatori_squadra(target),giocatoriUUID (dormiente). src/lib/rosa.tslegge dal database e ricade sucrapp-data.tsin caso di errore o assenza dati (DD-015).- Il completamento profilo (30/30/30/10) si calcola in app, non si persiste nel database.
- Lo storico certificati non viene conservato in v1 (coerente con DD-010).
- Le migration M1–M2 (tabelle, RLS, bucket) restano additive: solo
CREATE, nessunALTER/DROPsu schema esistente. - Raffina e attua quanto proposto in DD-015 per la rosa anagrafica, senza sostituire formalmente quella voce.
Riesame
- Quando
giocatori_squadraè stabile in produzione e il fallbackcrapp-data.tsnon serve più. - Quando si pianifica la convergenza verso UUID (DD-012, post v1.1).
- Se il CSI o il regolamento richiedono conservazione storica documenti o consensi privacy dedicati.
DD-017 — L'amministratore può compilare i dati al posto del giocatore
Data: agosto 2026
Stato: Accettata
Contesto
Il modulo Profilo Giocatore era costruito su un confine netto: ognuno scrive solo la propria riga, l'amministratore legge e scarica. Nella pratica quel confine blocca il lavoro che il modulo doveva togliere: se metà squadra non compila i propri dati, l'export per il tesseramento CSI resta incompleto e l'admin torna a chiedere le informazioni in chat — esattamente ciò che CrAPP deve eliminare. Inoltre le docs assegnavano già agli admin la gestione dei dati squadra (nome, cognome, numero, ruolo) e il reset del collegamento all'account (DD-016 regola 2), senza che esistesse una schermata per farlo.
Decisione
Dalla dashboard amministratore, un admin può:
- modificare i dati squadra di qualsiasi giocatore (nome, cognome, numero, ruolo);
- compilare e correggere i dati personali e del documento di qualsiasi giocatore;
- scollegare un account da un profilo, liberando lo slot.
Restano fuori, e non cambiano:
- i file (documento, certificato, foto): l'admin li scarica ma non li carica né li sostituisce. Un documento d'identità lo produce il suo titolare, e la catena di responsabilità deve restare leggibile;
- il giocatore, che continua a non poter toccare i propri dati squadra.
Alternative scartate
- Lasciare tutto al giocatore → l'export CSI resta incompleto e il lavoro amministrativo torna in chat, contro la missione del progetto.
- Dare all'admin anche l'upload dei file → confonde chi ha fornito un documento, su dati sanitari e d'identità dove serve il contrario.
- Un ruolo intermedio (segreteria) per i soli dati personali → un ruolo in più per una squadra sola, con gli stessi tre amministratori di adesso.
Conseguenze
- Il modello dei permessi non è più "ognuno i suoi": è "ognuno i suoi, più l'admin su tutti, tranne i file". Le policy RLS di M1 e M2 lo consentivano già, quindi non servono migration.
- Un admin può correggere un errore di battitura in un numero di documento senza inseguire il giocatore.
- Un admin vede e scrive dati personali altrui: è un potere reale, dato a tre persone su diciassette. Va assegnato con la stessa cura di prima (una riga in
user_roles, nessuna auto-promozione). - Il completamento del profilo smette di essere un indicatore di chi ha risposto e diventa un indicatore di quali dati mancano, chiunque li abbia inseriti.
Riesame
- Se la squadra cresce al punto da rendere sensato un ruolo di sola segreteria.
- Se serve tracciare chi ha modificato un dato: oggi non c'è audit, e con la scrittura condivisa la domanda prima o poi arriva.
DD-018 — Collegamento automatico giocatore↔account per email
Data: settembre 2026
Stato: Accettata
Contesto
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) 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 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é 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
/benvenutofinché non esce e riprova con l'account giusto.
Riesame
- Se in futuro serve un'assistenza admin diretta dal flusso di login invece che da
/admin.
Decisioni in valutazione
DD-014 — Convergenza schema database (eventi e presenze)
Data: —
Stato: In valutazione
Contesto
Esistono due modelli paralleli: tabelle “legacy” usate dall’app (eventi_app, risposte_presenze) e tabelle “nuove” con autenticazione e vincoli (eventi, presenze, giocatori UUID).
Decisione proposta
Unificare gradualmente sul modello autenticato, dopo auth e profilo stabili.
Perché non ora
Rischio regressioni su calendario e presenze, moduli più usati della squadra.
Riesame previsto
Post v1.1, con migration e test dedicati.
DD-015 — Rosa anagrafica: da codice hardcoded a database
Data: 3 settembre 2026
Stato: Accettata
Contesto
La lista giocatori viveva nel codice sorgente (src/lib/crapp-data.ts). Il database aveva già
giocatori_squadra (migration M1) popolata ma non letta da nessuna schermata tranne
/benvenuto e /admin: «Aggiungi giocatore» e «Disattiva giocatore» della dashboard non
avevano effetto su Squadra, Presenze, Pagelle, Badge e Scout, mantenendo gli stessi ID finché
non si farà DD-012.
Decisione
useRosa() (e con lei useIo, useObiettivi) legge ora giocatori_squadra tramite
useGiocatoriSquadra(), filtrando solo i giocatori attivo. Tutti i punti che prima
importavano la lista statica (convocatiEvento, compleanniEventi, completaTurni,
csvScoutMatch, i widget di voto/scout/palloni, le due route API che mandano push) sono stati
agganciati allo stesso hook o, lato server, a leggiGiocatoriSquadra()
(src/lib/giocatori-squadra.server.ts, stesso pattern di eventi.server.ts).
Conseguenze
- Un giocatore aggiunto o disattivato dalla dashboard admin ora si riflette ovunque, non solo
in
/benvenutoe/admin. giocatori_squadranon ha ancora una colonna per la data di nascita: per i 17 giocatori storici resta quella dicrapp-data.ts(nascitaPerId, lookup per id); un giocatore aggiunto dopo la migrazione non ha nascita nota finché la colonna non esiste. Follow-up da aprire quando serve davvero.src/lib/crapp-data.tsresta come seed storico e fallback (rosaFallback()), non più come fonte viva.
DD-019 — Il branch dei commit lo decide l'utente
Data: 4 settembre 2026
Stato: Accettata — sostituisce DD-003
Contesto
DD-003 prevedeva di lavorare su develop e portare su main solo dopo i test. Nella pratica
è successo il contrario: main è arrivato a 43 commit di vantaggio su develop, che è rimasto
fermo. Una regola che nessuno segue è peggio di nessuna regola, perché rende inaffidabile tutto
il resto del documento — e con più assistenti AI in gioco il rischio vero non era il branch
sbagliato, ma un agente che committa o pusha per conto suo.
Decisione
È l'utente a dire su quale branch va un commit. L'assistente può consigliare un branch
dedicato quando la modifica è rischiosa o parallela ad altro lavoro, ma non cambia branch, non
committa, non fa push e non apre PR di propria iniziativa. In assenza di indicazioni si lavora
dove si trova il repository, di fatto main.
Alternative scartate
- Tenere DD-003 e riallineare
develop→ si sarebbe rotta di nuovo alla prima fretta. - Dismettere
develop→ si perderebbero le preview Vercel, utili quando servono davvero.
Conseguenze
mainè insieme produzione e branch di lavoro: ogni commit deve lasciare l'app funzionante, quindi la rete di sicurezza sono i test (vedi DD-020), non il branch.developesiste ancora ma è indietro: la sua preview Vercel non rappresenta lo stato attuale finché non viene riallineata.
Riesame
Se il team cresce oltre una persona che scrive codice, o se un lavoro lungo ha bisogno di stare
fuori produzione per più di qualche giorno.
DD-020 — Una funzione modificata senza test non è finita
Data: 4 settembre 2026
Stato: Accettata
Contesto
Con main come branch di lavoro (DD-019) non c'è più un ambiente di prova tra il codice e i
giocatori. La suite in test/ esisteva già ma scriverla era di fatto facoltativo, e i difetti
trovati dai test sono arrivati a posteriori (la sessione Scout Live che non scadeva mai, le
serie di presenze ferme a zero per settimane).
Decisione
Chi aggiunge o modifica una funzione scrive o aggiorna il test nello stesso lavoro, e i test
devono essere verdi prima di consegnare. Non si commenta un test che fallisce né si indebolisce
un'asserzione per farla passare: se il comportamento voluto è cambiato, si aggiorna il test
dicendo perché.
Alternative scartate
- Test solo sui moduli critici → il confine «critico» si sposta a ogni fretta.
- Introdurre un framework di test → la suite bun con
node:assertfunziona e non aggiunge dipendenze (vedi test/README.md).
Conseguenze
- La logica di dominio va tenuta separabile dagli hook (
*-core.ts), altrimenti non è testabile intest/unit/senza rete. - Le modifiche costano un po' di più; le regressioni in produzione costano di più.
Riesame
Se comparisse un ambiente di staging stabile che rende superflua parte della copertura.