v0.7.2
2026-08-14Fixed
- Le migration sono compatibili con PgBouncer in transaction pooling — le connessioni production non usano prepared statement nominali che possono riferirsi a una sessione server gia' rilasciata al pool.
Version v0.29.3
apps-1 e apps-2 dietro al load balancer; l'avvio resta seriale per evitare migrazioni concorrenti.
db-support — web e worker non dipendono più da file SQLite locali; completato anche lo schema Solid Cable necessario sui database nuovi.
/version, che serve alle macchine per sapere quale versione gira davvero, continua a rispondere col dato grezzo — lì "sconosciuto" è la risposta onesta.
scout esisteva ma si poteva alzare solo dalla console del server. Ora si dà e si toglie il ruolo dalla scheda di una persona, e c'è una sezione Scouting che elenca chi porta iscrizioni col proprio QR con quante ne porta in tutto e negli ultimi trenta giorni. La pagina di ciascuno mostra i quattro contatori, tre percentuali di qualità, l'andamento dell'ultimo mese e chi ha portato, con nome ed email veri e il link alla scheda: serve a riconoscere chi si iscrive account finti da solo. Nell'app degli scout continuano a uscire solo le iniziali — quello resta il contratto verso lo scout.
PUT/DELETE .../accounts/:id/scout), non un verbo custom, perché assegna il codice personale. Togliere il ruolo conserva scout_code: il flag da solo ferma le nuove attribuzioni, e così riabilitare la persona fa ripartire lo stesso QR già stampato sui volantini. Un account sospeso non può diventare scout, perché il suo codice non funzionerebbe.
/eventi in italiano, /en/events in inglese, e così per ogni pagina pubblica. Prima la versione inglese esisteva ma nessun indirizzo la esponeva: il selettore cambiava la lingua nella sessione e restava sulla stessa pagina, quindi non era né condivisibile né trovabile. Ora è un link, e chi lo copia manda davvero la pagina in inglese. Tutti gli indirizzi storici rimandano ai nuovi conservando percorso e parametri, così i link già pubblicati altrove continuano a funzionare e le campagne non perdono l'attribuzione.
/eventi?q=techno non diventa una pagina a sé per ogni combinazione di filtri.
/sitemap.xml, divisa in sezioni e generata al momento. Gli eventi finiti ne escono, quelli ancora in corso restano — alle 23 sono i più rilevanti di tutti. Fuori produzione non esiste: staging non deve annunciare i propri indirizzi.
config/routes/*.rb, host canonico da ENV e blocco dell'indicizzazione fuori produzione.
indexable!. L'errore costoso è asimmetrico: dimenticare noindex su un'area riservata la espone, dimenticare indexable! su una pagina pubblica la rende invisibile e ce ne si accorge subito.
Website::LegalDocument) e la cookie policy finalmente scritta. La privacy dice come si chiude l'account e cosa viene cancellato.
privaterelay, che inoltra davvero.
province (codice o nome provincia, maiuscolo o minuscolo), così l'app mobile può aprirsi sulla zona dell'utente invece che su tutta Italia. - Promoter e crew non hanno un indirizzo proprio: la loro zona è quella dell'account owner del team (OwnerProvinceFilterable, semi-join che non tocca la paginazione a cursore). Chi non ha owner attivo o zona resta fuori dai risultati filtrati. - System::ServiceArea.code_for normalizza codice e nome provincia in un punto solo. - Indici parziali su accounts.province ed events.province.
accounts.province è normalizzata e validata. AccountSerializer espone province_name. Task accounts:backfill_province (con DRY_RUN=1) per gli account esistenti.
/cli/v1 per clubbel-cli — il backend parla con una CLI da terminale, riservata agli account god. Login dal browser con device flow (RFC 8628): la CLI mostra un codice breve, chi è già loggato lo approva da /cli/authorize, e la CLI riceve un token clb_u_ valido 90 giorni. Il segreto esiste una volta sola — in tabella c'è solo il suo digest SHA-256. - Endpoint dati: whoami, eventi e venue in elenco (paginati) e in scheda, le quattro transizioni di un evento (approve/reject/publish/cancel), le due di una venue (approve/reject), e le quattro tassonomie. - Un filtro status inesistente ora risponde 422 dicendo quali valori sono ammessi, invece di restituire una lista vuota indistinguibile da "nessun risultato". - Paginazione a offset (page/per, meta.total_pages), diversa dal cursore usato da /api/v1: una CLI ha bisogno di dire "pagina 2 di 5", non di scorrere all'infinito.
/cli/v1, sul polling del device flow (per codice, non per IP) e sulla pagina di approvazione.
Events::CreateService scrive province: nil per gli eventi ospitati in un locale (il caso normale, location_mode: "venue_search"), quindi ?province=RN vedeva solo gli eventi google_place. Ora la zona di un evento è la sua oppure quella del locale, anche nella ricerca della mappa.
timestamp without time zone in UTC e Postgres scarta l'offset: il confronto scivolava di un paio d'ore. Su promoter, crew e locali la pagina successiva ripeteva la precedente; sugli eventi (confronto >) saltava gli eventi in mezzo. Cursore ora in UTC con microsecondi, e id confrontato come uuid invece che come testo.
Gemfile.lock: solid_queue 1.4.0 → 1.6.0, solid_cable 4.0.0 → 4.0.2, alba 3.10.0 → 3.11.0, aws-sdk-s3 1.227.0 → 1.228.1, googleauth 1.17.1 → 1.17.3, closeyourit-ruby 0.6.0 → 0.6.1, thruster 0.1.22 → 0.1.23.
selenium-webdriver 4.45.0 → 4.46.0, simplecov 0.22.0 → 1.0.3.
proxy.ssl da true a false: l'app serve da dietro apps-lb. kamal-proxy prende i certificati con la sfida HTTP-01 sul proprio host, e con piu' server dietro un bilanciatore la verifica arriva al server sbagliato una volta su due. - Le app mobile puntano a questo host e non fanno certificate pinning (verificato): il cambio di certificato, da quello per-host di kamal-proxy al *.bussolarialessio.me dell'LB, non le tocca. - Nessuna modifica applicativa: forward_headers e' gia' il default con ssl: false, e config.assume_ssl = true fa considerare sicura ogni richiesta.