Novità

Versione v0.29.0

Tutte le versioni (90)

v0.6.0

2026-08-12

Modificato

  • Clubbel può essere servito da due nodi applicativi — il web viene distribuito su apps-1 e apps-2 dietro al load balancer; l'avvio resta seriale per evitare migrazioni concorrenti.
  • Queue, Cache e Cable usano PostgreSQL condiviso su db-support — web e worker non dipendono più da file SQLite locali; completato anche lo schema Solid Cable necessario sui database nuovi.

v0.5.0

2026-08-11

Modificato

  • La versione del sistema al posto della mail nei pannelli — in fondo alla barra laterale di Valhalla e dei pannelli di locali, crew e organizzatori c'erano foto, nome, mail e uscita, ma nome e uscita stanno già nella barra in alto: quello spazio ripeteva cose già dette e mostrava una mail che non serviva a nessuno. Ora c'è la versione, così da qualsiasi schermata si vede quale versione è online — utile soprattutto per capire a colpo d'occhio se si sta guardando la prova o il sito vero. La stessa riga compare in fondo al sito pubblico e all'area personale.
  • Mentre si sviluppa in locale la versione della pubblicazione non esiste: lì la riga legge il numero in cima a questo file invece di scrivere "sconosciuto". L'indirizzo /version, che serve alle macchine per sapere quale versione gira davvero, continua a rispondere col dato grezzo — lì "sconosciuto" è la risposta onesta.
  • Il pulsante di uscita resta dov'era, nella barra in alto: dalla barra laterale è stato tolto perché era il secondo.

v0.4.0

2026-08-11

Aggiunto

  • Gestione degli scout in Valhalla (CLRA-31) — il flag 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.
  • L'abilitazione è una sotto-risorsa singleton (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.
  • La terza percentuale di qualità dice quanti degli iscritti sono ancora attivi: hanno una sessione aperta più di un giorno dopo l'iscrizione. Non "almeno un accesso", perché la conferma dell'email e ogni rinnovo del token creano già una sessione e il conteggio grezzo avrebbe dato quasi il 100% a qualunque scout. È una fotografia di adesso e non uno storico — le sessioni scadono dopo trenta giorni e il logout le cancella — e il tooltip della card lo dice.

Modificato

  • Via la forma a pillola da tutta l'interfaccia (CLRA-32) — le pill dei filtri sulla mappa, i chip dei filtri attivi nei ventidue elenchi di gestione, i badge del sito, la barra flottante e il bottone tondo della barra in basso avevano gli angoli completamente arrotondati: ora sono smussati come tutto il resto. Restano tonde solo le cose che devono esserlo — pallini di stato, barre di avanzamento, decorazioni e i pin della mappa. Il design system vietava già quella forma, ma faceva un'eccezione per i comandi sopra la mappa: da lì si era propagata a novantotto punti dell'interfaccia. L'eccezione è stata tolta.

Corretto

  • Il titolo di una sezione passava sopra anche alla colonna accanto (CLRA-33) — nelle pagine di dettaglio del pannello di gestione il titolino "Dettagli" si allungava per tutta la larghezza, quindi sembrava intestare pure la colonna di destra. Sulla scheda di una persona quella colonna è la zona pericolosa: sospendi e banna sembravano dettagli. Ora ogni colonna ha il suo titolo, alla stessa altezza, e i due riquadri partono allineati. Vale per tutte e nove le pagine che usano quella griglia.
  • La zona pericolosa era l'unico riquadro di tutto il pannello costruito a mano invece che col pezzo standard: ora è uguale agli altri. Perde il bordo rosso, tiene i suoi bottoni e il titolo "azioni irreversibili".

v0.3.0

2026-08-10

Aggiunto

  • Il sito parla due lingue con due indirizzi (CLRA-12) — /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.
  • Anteprime vere quando si condivide un link — titolo, descrizione e immagine di copertina al posto del solo nome del sito. Ogni pagina dichiara anche l'indirizzo buono da indicizzare: gli elenchi filtrati puntano alla pagina nuda, così /eventi?q=techno non diventa una pagina a sé per ogni combinazione di filtri.
  • Gli eventi e i locali si descrivono ai motori di ricerca — data con fuso orario, luogo, prezzo, artisti, orari di apertura, in un formato che permette di comparire nei caroselli e nelle schede laterali. Se manca un dato obbligatorio non si dichiara niente: un blocco incompleto viene segnalato come errore e può far scartare anche il resto.
  • Mappa del sito su /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.
  • Icone dell'app e anteprima social — erano referenziate dal manifest ma non erano mai esistite, quindi ogni installazione della web app faceva due richieste a vuoto.

Corretto

  • L'import da Instagram non creava l'evento quando il post aveva una foto — il file scaricato veniva passato in un formato che l'archivio allegati rifiuta, e l'errore spariva dentro un messaggio generico. Ogni post con immagine falliva in silenzio.
  • Le copertine non si vedevano da nessuna parte — il controllo "c'è un'immagine?" era sempre vero, quindi il segnaposto non compariva mai e al suo posto restava un'immagine rotta.
  • Un indirizzo con un cursore di paginazione inventato rispondeva errore 500 — ora vale come "parti dall'inizio".
  • Il recupero password si poteva tentare più volte del consentito cambiando il prefisso di lingua nell'indirizzo. L'area di accesso non ha più prefissi.

v0.2.0

2026-08-10

Aggiunto

  • Le schede di eventi, locali, artisti e organizzatori sono pagine vere (CLRA-12) — prima erano tre righe nascoste più uno script che apriva un pannello laterale: il contenuto arrivava solo via XHR, che i motori di ricerca non fanno. Ora la pagina è leggibile senza JavaScript, gli elenchi la linkano davvero e da ogni scheda si risale all'indice con le briciole di navigazione. Le route sono divise per area in config/routes/*.rb, host canonico da ENV e blocco dell'indicizzazione fuori produzione.
  • Politica di indicizzazione col default invertito — tutto resta fuori dai motori di ricerca finché un controller non dichiara 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.
  • Testi veri di privacy, cookie e termini (CLRA-14) — al posto del segnaposto "Policy in aggiornamento", con i dati societari reali in un punto solo (Website::LegalDocument) e la cookie policy finalmente scritta. La privacy dice come si chiude l'account e cosa viene cancellato.
  • Accesso con Apple — dove c'è il login Google, App Store pretende anche il suo (guideline 4.8). Apple non ha un endpoint che valida il token: la firma si verifica qui, con le chiavi pubbliche in cache dodici ore. Il nome arriva solo al primo accesso e l'email può essere un alias privaterelay, che inoltra davvero.
  • Ricerca di vie e città sulla mappa (CLRA-10) — la ricerca trovava solo locali ed eventi già in archivio. Ora suggerisce anche indirizzi, con i tempi di percorrenza nella lista eventi e la provincia da scegliere in elenco invece che da digitare a mano.
  • Motion sul sito pubblico — una sorgente unica di durate ed easing invece di transizioni sparse: l'uscita è sempre più rapida dell'entrata, e chi ha chiesto meno movimento non ne vede nessuno, view transition comprese.
  • CLRA-13: filtro per zona su eventi, locali, organizzatori e artisti — le quattro liste della ricerca accettano 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.
  • CLRA-13: il campo città dell'onboarding è a suggerimenti (Google Places) e salva anche la provincia; accounts.province è normalizzata e validata. AccountSerializer espone province_name. Task accounts:backfill_province (con DRY_RUN=1) per gli account esistenti.
  • Canale /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.
  • Il token della CLI muore col cambio password e con la disattivazione dell'account, come già facevano le sessioni: cambiare password è il modo in cui si reagisce a una credenziale compromessa, e lasciare vivo il token per altri 90 giorni la lascerebbe compromessa.
  • Rate limit su /cli/v1, sul polling del device flow (per codice, non per IP) e sulla pagina di approvazione.

Corretto

  • La chiusura dell'account cancella davvero i dati personali — oltre a email e nome vengono ora rimossi data di nascita, genere, città, provincia, biografia, telefono, foto profilo, generi musicali, il collegamento con Google e Apple e gli identificativi delle notifiche. Il collegamento Google restava: bastava un "accedi con Google" per rientrare in un account chiuso.
  • Le briciole di navigazione sparivano dall'HTML — la loro etichetta di accessibilità non era tradotta e il segnaposto conteneva virgolette, che chiudevano l'attributo a metà rompendo il markup. Chi le cercava, motori di ricerca compresi, non le trovava.
  • CLRA-13: il filtro per provincia sugli eventi non trovava quasi nulla — 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.
  • CLRA-13: la paginazione a cursore saltava o ripeteva risultati — il cursore veniva emesso in ora locale con offset, ma le colonne sono 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.

v0.1.28

2026-08-04

Modificato

  • Aggiornamento dipendenze — nessuna modifica applicativa, solo 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.
  • Dipendenze di sviluppo: selenium-webdriver 4.45.0 → 4.46.0, simplecov 0.22.0 → 1.0.3.

v0.1.27

2026-07-30

Modificato

  • Il TLS passa al load balancer — 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.

v0.1.26

2026-07-26

Corretto

  • CLFL-48: la creazione di un Locale (e di Artista/Organizzatore con cover) non si finalizzava — Member::{Venue,Crew,Promoter}Request#to_payload passava l'oggetto ActiveStorage::Attached::One invece del blob, causando Could not find or build blob: expected attachable. Ora passa cover_image.blob.
  • CLFL-47: i link website/social inseriti senza schema (www.sito.com) facevano fallire la creazione di Artisti (e Locali/Organizzatori) con website.invalid. Nuovo concern UrlNormalizable normalizza a https://… prima della validazione (form contatti crew/promoter, info promoter, location venue); gli schemi non-http (javascript:, ecc.) restano rifiutati.

v0.1.25

2026-07-25

Aggiunto

  • CLFL-40: foto profilo (fino a 3) per Artisti e Organizzatori. has_many_attached :photos su Crew/Promoter e sui draft, caricabili via wizard (photos[]) e via PATCH profilo entità (crew[photos][]); serializer espone photos: [url]; validazione max 3 + content_type/size. Index crew/promoter con eager loading degli attachment per evitare N+1.

v0.1.24

2026-07-24

Corretto

  • CLFL-37: la creazione di un nuovo Locale (e l'autocomplete indirizzi/città) non mostrava suggerimenti — l'endpoint API GET /api/v1/member/lookups/places non esisteva (404). Aggiunto Api::V1::Member::Lookups::PlacesController (mirror del web) + route. Geo::PlacesAutocompleteService traduce ora address→street_address/route/premise (filtra indirizzi, non POI) mantenendo i primaryType validi di Table B (establishment, ecc.). Sblocca anche l'autocomplete città del profilo.

Rimosso

  • CLFL-36: rimosso completamente il campo Capienza dai Locali su tutte le superfici — drop colonne DB venues.capacity e member_venue_requests.capacity (migration), serializer, form object, strong params, wizard mobile/web, vista pubblica e i18n.