- Spezza il registro delle decisioni in docs/decisions/DD-XXX.md, con indice - Ripulisce DATABASE.md dalla storia delle migration e aggiunge la sezione Lettura - Riduce PROJECT_STATE.md a una pagina; la procedura di allestimento passa in OPERATIONS.md - Aggiunge OPERATIONS.md, GLOSSARIO.md, trappole note e checklist in ARCHITECTURE.md - Sintetizza la copertura test di badge.md e documenta docs/archive - Allinea AGENTS.md, README.md e la regola Cursor (tolto l'obbligo di develop, in contrasto con DD-019) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
53 lines
3.1 KiB
Markdown
53 lines
3.1 KiB
Markdown
# DD-027 — Chi vota deve essere convocato, non solo autenticato come sé stesso
|
|
|
|
**Stato:** accettata · **Data:** 8 settembre 2026
|
|
|
|
**Contesto**
|
|
Un audit del modulo Badge (`docs/modules/badge.md`) ha trovato due filtri rimasti solo
|
|
applicativi dopo DD-023: la policy di M11 garantisce che `votante_id` sia lo slot collegato
|
|
all'account di chi scrive, ma non controlla che **votante e votato fossero convocati**
|
|
all'evento — un utente che scrive direttamente su PostgREST (bypassando l'interfaccia) poteva
|
|
votare o essere votato in una partita a cui non aveva partecipato, gonfiando `mediaVoto`,
|
|
`mvp` o un badge social a piacere. Allo stesso modo, `eventi_app.pagelle_chiuse` nascondeva
|
|
solo i bottoni in UI: un voto pagella "fuori tempo" restava tecnicamente possibile.
|
|
|
|
**Decisione**
|
|
La policy "Ognuno gestisce i propri voti ..." di `pagelle_voti`, `mvp_voti` e
|
|
`badge_social_voti` (M11) guadagna un controllo aggiuntivo tramite la funzione
|
|
`evento_permette_voto()` (migration `m13_convocati_e_pagelle_chiuse`): verifica che sia
|
|
`votante_id` sia `votato_id` compaiano in `eventi_app.convocati` per quel `match_id`
|
|
(`convocati` vuoto = tutta la rosa, la stessa convenzione di `convocatiEvento()` in
|
|
`eventi.ts`), e — solo per le pagelle — che `pagelle_chiuse` sia falso. Le policy admin
|
|
restano invariate e permissive: un amministratore deve poter correggere un voto anche fuori
|
|
convocazione o dopo la chiusura.
|
|
|
|
Il controllo si ferma alla **convocazione**, non alla **presenza reale**: per l'MVP, ad
|
|
esempio, l'interfaccia limita già il voto ai soli presenti/in ritardo
|
|
(`usePresenzeEvento`), un filtro più stretto che resta solo applicativo — un convocato ma
|
|
assente passa ancora a livello database. Stringere fino a quel punto avrebbe richiesto
|
|
leggere `risposte_presenze` dentro la policy, un salto di complessità non giustificato
|
|
dall'audit che ha originato questa decisione.
|
|
|
|
**Alternative scartate**
|
|
|
|
- Un trigger `BEFORE INSERT/UPDATE` invece di RLS → si applicherebbe anche alla service key
|
|
e agli admin, bloccando correzioni legittime fuori convocazione; la RLS, applicata solo
|
|
alla policy non-admin, li esclude naturalmente.
|
|
- Controllare anche la presenza reale (`risposte_presenze`), non solo la convocazione →
|
|
scope maggiore del gap trovato in audit, e specifico dell'MVP (pagelle e badge social non
|
|
hanno un concetto di "presente" distinto da "convocato" nell'interfaccia attuale).
|
|
|
|
**Conseguenze**
|
|
|
|
- Un evento senza `convocati` esplicito (lista vuota, il caso più comune oggi) non cambia
|
|
comportamento: tutta la rosa resta votabile, come prima.
|
|
- I test di `test/integration/permessi.test.ts` sono la definizione eseguibile anche di
|
|
questa parte della tabella dei permessi (voti non convocati rifiutati, `pagelle_chiuse`
|
|
rifiutata a database, controlli positivi che provano che un voto legittimo passa ancora).
|
|
- Resta un gap conosciuto e documentato (non quello risolto qui): che il votante fosse
|
|
davvero presente, non solo convocato, per MVP/pagelle/badge social.
|
|
|
|
**Riesame**
|
|
Se un giorno servisse bloccare anche il voto di un convocato-ma-assente a livello database,
|
|
non solo in UI.
|