Cronologia versioni
# Changelog
Tutte le modifiche rilevanti a questo progetto saranno documentate in questo file.
## [Unreleased]
### Features
* **identità Eventix**: la navigazione pubblica torna a mostrare il lockup ufficiale (`static/img/eventix-lockup.png`, ricavato da `Logo.png` con trasparenza ripulita e dimensioni dichiarate `800×244`) affiancato dal payoff *Smart event ticketing*. Logo, wordmark e palette blu/viola sono ora coerenti tra vetrina, pagine legali, footer e PWA.
* **splash iniziale**: all'avvio degli utenti anonimi compare una breve schermata di brand con il lockup, una barra di avanzamento e il payoff, visibile una sola volta per sessione e non bloccante. Lo splash rispetta `prefers-reduced-motion`, ha un fallback senza JavaScript e viene chiuso al massimo dopo 2,4 s. Il manifest PWA usa `background_color`/`theme_color` `#090e22` per allineare anche lo splash di sistema.
* **vetrina desktop-first**: nuova hero navy a due colonne con login, anteprima prodotto costruita in HTML/CSS, funzioni in griglia bento, workflow editoriale, trust panel e CTA finale. `static/css/public.css` isola il linguaggio visivo pubblico dal backoffice e mantiene il layout completo da 320 a 1440 px; navbar chiara, footer, banner cookie e pagine legali sono riallineati al brand.
* **audit GDPR download**: `legal_document_downloads` registra anche `document_title`, `ip_address` e `user_agent`, con migrazione idempotente per i database esistenti e indice `(document_slug, downloaded_at DESC)`.
### Tests
* `tests/check_public_site.py`: verifica lockup dimensionato e splash di brand, anteprima prodotto desktop, CSS pubblico responsive e colori PWA coerenti.
* `tests/check_legal_gdpr.py`: verifica le nuove colonne di audit GDPR e i relativi indici nella migrazione.
### Documentation
* `ARCHITETTURA.md`, `MANUALE.md`, `docs/MANUALE_PUBBLICO.md` e `README.md` aggiornati su identità, splash, vetrina desktop-first e audit download GDPR.
## [0.12.0](https://github.com/simograndi/taskman/compare/taskman-v0.11.1...taskman-v0.12.0) (2026-10-20)
### Features
* **vetrina pubblica**: `/` per i visitatori anonimi non reindirizza più al login ma mostra una pagina di presentazione del software (funzioni, flusso di lavoro e punti di fiducia) con il **riquadro di accesso sticky a destra** su desktop. Gli utenti autenticati continuano a vedere la dashboard; `/login` usa la stessa vetrina.
* **pagine legali integrate**: `templates/legal/base_legal.html` estende ora `base.html`: privacy, termini, cookie policy e contatti usano la navigazione pubblica, il footer e il banner cookie del portale, senza topbar o footer duplicati. Hero, tab, indice e callout di supporto sono riallineati alla palette Eventix.
* **favicon locale**: nuova variante `local` (`static/icons/favicon-local.png|ico`) servita quando l'host è `127.0.0.1`, `localhost` o `::1`; a seguire Staging (`favicon-staging.*`) e Produzione (`favicon-prod.*`). La stessa priorità vale per `GET /favicon.ico` e per i tag `<link rel="icon">`.
* **SEO della home**: la vetrina resta `index, follow` in Produzione e `noindex, nofollow` in Staging, con canonical su `PROD_DOMAIN` e sitemap invariata.
* **layout pubblico responsive**: nuova navbar sticky con menu collassabile sotto 992 px, hero editoriale senza immagini non dimensionate, funzioni in griglia 3/2/1 colonne, workflow in card e pannello accesso sticky senza overflow. Verificato senza overflow orizzontale da 320 a 1440 px.
* **PWA e mobile**: viewport con `viewport-fit=cover`, altezza `100dvh`, target touch da 44 px, safe area iOS su navbar/footer/banner e manifest arricchito (`id`, `lang`, `display_override`, shortcut, icone maskable).
* **banner cookie compatto**: scheda flottante da 430 px su desktop e tre azioni in riga su mobile (circa 150 px di altezza a 390 px), con pulsante di chiusura che registra i soli cookie necessari.
* **crediti**: rimosso lo splash gigante `credits-splash` che mostrava `Designer - White.png` (1254×1254) sopra la modale; resta il logo 64 px nel corpo.
### Bug Fixes
* la vetrina mobile non viene più coperta dal banner cookie a tutta larghezza e il logo pubblico non usa più l'immagine sorgente 1536×1024: il marchio è un blocco CSS compatto e tutte le immagini residue restano vincolate.
* l'indice delle pagine legali torna sticky su desktop (`align-self: stretch` sulla colonna) e diventa una riga di chip scorrevole sotto 992 px.
### Tests
* nuovo `tests/check_public_site.py`: vetrina anonima, login, dashboard autenticata, shell legale condivisa, indicizzazione per ambiente, priorità delle tre favicon, validità dell'ICO locale, layout responsive, navbar collassabile, banner cookie compatto e campi del manifest PWA.
* `tests/check_promotion.py` e `tests/check_legal_gdpr.py` aggiornati per l'host locale, l'asset `favicon-local.ico` e il layout legale che estende `base.html`.
### Documentation
* `ARCHITETTURA.md`, `MANUALE.md`, `docs/MANUALE_PUBBLICO.md` e `README.md` aggiornati su vetrina pubblica, login sticky, pagine legali integrate e favicon locale.
## [0.11.1](https://github.com/simograndi/taskman/compare/taskman-v0.11.0...taskman-v0.11.1) (2026-10-20)
### Features
* calendario eventi: flag rapido **attivo/non attivo** per gli admin nell'elenco (`POST /events/<id>/toggle-active`). L'attivazione è immediata e senza conferma; la disattivazione chiede conferma in una modale con il riepilogo di richieste collegate, biglietti richiesti ed emessi (biglietti/pass), ricordando che i dati già registrati restano invariati. I nuovi eventi nascono **attivi** (con conferma al salvataggio) e la duplicazione resta **non attiva** finché non viene verificata.
* importazione eventi da file (prevista): al termine dell'importazione verrà chiesto se attivare gli eventi importati, che verranno creati **non attivi** per consentire la verifica di date e posti.
### Bug Fixes
* disponibilità eventi: gli utenti vedono solo il **semaforo sul totale** (verde = ok, giallo = posti limitati/in esaurimento dall'80% richiesto, rosso = posti esauriti) e non più i numeri. Il dettaglio evento mostra il semaforo al posto dei posti per zona e del totale; admin/editor continuano a vedere numeri e zone. Le soglie sono centralizzate in `availability_status()` (usata da `/events`, form nuove richieste e badge di `manage_request`) e il messaggio "La richiesta non è garantita a causa dell'esaurimento dei posti disponibili." resta nel form richieste con semaforo rosso.
### Documentation
* `MANUALE_ADMIN.md` (§1), `MANUALE.md` (*Eventi*), `ARCHITETTURA.md` (§6-octies) e `docs/MANUALE_OPERATORI_ADMIN.md` (§7) documentano il flag rapido attivo/non attivo, il default attivo dei nuovi eventi, la conferma di disattivazione con riepilogo e il comportamento previsto dell'importazione da file.
### Tests
* `tests/check_request_edit_manage.py`: nuove verifiche sul semaforo (soglie 80%/100%, evento senza posti), rendering del dettaglio evento per utente (solo colore ed etichetta, nessun numero o zona) e per admin (numeri e zone visibili), semaforo rosso a esaurimento e messaggio `sold_out_message` ancora collegato al form richieste.
* `tests/check_request_edit_manage.py` e `tests/check_management_ui.py`: verifica che `POST /events/add` crei l'evento attivo di default, che `POST /events/<id>/toggle-active` attivi/disattivi (400 azione non valida, 404 evento assente, 403 ruolo user), che il template dell'elenco esponga il flag, la modale di riepilogo e la conferma di creazione.
## [0.11.0](https://github.com/simograndi/taskman/compare/taskman-v0.10.2...taskman-v0.11.0) (2026-10-20)
### Features
* layout compatto delle pagine di management: le azioni di riga (eventi, luoghi, organizzatori, utenti, biglietti, richieste) sono pulsanti a icona `btn btn-sm icon-btn` con tooltip nativo `title` e `aria-label`, raggruppati in `.action-group`; in Staging anche i pulsanti di promozione di `_promotion.html` diventano icone (pubblica/aggiorna, rimuovi dalla produzione, flag demo) e le righe restano leggibili.
* tabelle di management responsive: sotto 576 px le righe diventano schede impilate con l'etichetta di colonna (`table-stack` + `data-label`, cella azioni `.table-cell-actions`), mentre sotto 992 px i pannelli riducono il padding, i titoli di sezione vanno a capo e l'elenco eventi porta i pulsanti su una seconda riga. La gestione richiesta resta a scorrimento orizzontale per non tagliare i dropdown dei combobox.
* badge d'ambiente più compatto su smartphone per non coprire i contenuti in fondo alla pagina.
### Bug Fixes
* badge e favicon coerenti anche con `FLASK_ENV=staging`: `app_environment()` considera Staging Mode sia `development` sia `staging` ed è l'unica fonte per badge, favicon, meta robots/`X-Robots-Tag`, `robots.txt`/`sitemap.xml` e modulo Deploy. Prima un'istanza con `FLASK_ENV=staging` mostrava l'icona STG ma il badge verde **Official**, consentiva l'indicizzazione e teneva bloccato il modulo Deploy; ora mostra **Staging Mode** (giallo) con l'icona STG e si comporta come staging.
### Documentation
* `ARCHITETTURA.md` (§6-septies), `MANUALE.md` (*Azioni rapide e layout su mobile*), `docs/MANUALE_OPERATORI_ADMIN.md` (§7 con le convenzioni per le nuove viste e il nuovo test) e `docs/MANUALE_PUBBLICO.md` (FAQ mobile) aggiornati.
### Tests
* nuovo `tests/check_management_ui.py`: verifica ganci CSS e breakpoint, `data-label` su tutte le celle delle tabelle impilate, `title`/`aria-label` su ogni `.icon-btn`, assenza di azioni testuali nelle celle Azioni, esclusione di `manage_request.html` dalla modalità impilata e compilazione di tutti i template.
## [0.10.2](https://github.com/simograndi/taskman/compare/taskman-v0.10.1...taskman-v0.10.2) (2026-10-20)
### Bug Fixes
* favicon dinamica non visualizzata: i file `static/img/favicon_*.ico` dichiaravano 256×256 ma contenevano un bitmap 1254×1254 (ICO non valido, scartato dai browser). Le icone ora stanno in `static/icons/` (`favicon-staging.png|ico` arancione con badge STG, `favicon-prod.png|ico` ufficiale, `logo.png`, `apple-touch-icon.png`, `icon-192.png`, `icon-512.png`) e si rigenerano con `python tools/generate_favicons.py`.
* `GET /favicon.ico` serve l'ICO dell'ambiente corrente e i tag `<link rel="icon">` usano `?v={{ app_version }}` come cache buster: una favicon già in cache non resta più bloccata dopo il deploy.
* `static/manifest.webmanifest` allineato a `/static/icons/`: percorsi assoluti, icona 512 `maskable` e file presenti su disco.
### Documentation
* manuali pubblico e operatori, `ARCHITETTURA.md`, `README.md` e `MANUALE.md` aggiornati con le icone di `static/icons/`, la favicon dinamica per ambiente e il troubleshooting della cache delle favicon.
## [0.10.1](https://github.com/simograndi/taskman/compare/taskman-v0.10.0...taskman-v0.10.1) (2026-10-20)
### Bug Fixes
* doppio deployment a ogni promozione: con l'integrazione GitHub di Coolify il push su `main` avvia già un deploy (`is_webhook: true`) e l'hook manuale ne avviava un secondo (`is_api: true`). Prima dell'hook l'app legge `GET /api/v1/deployments/applications/<uuid>` (uuid ricavato da `PROD_DEPLOY_HOOK_URL`) e attende fino a `DEPLOY_AUTODEPLOY_GRACE_SECONDS` (default 8) il deployment webhook del merge; se c'è, l'hook non parte. Se l'API non è raggiungibile il deploy manuale prosegue con un avviso nell'esito.
* hook deduplicato in modo atomico: la prenotazione avviene prima della `POST`, quindi due richieste sovrapposte (doppio click) non inviano entrambe; gli errori rilasciano subito la prenotazione per permettere il retry.
* l'hook manuale viene saltato anche se Coolify ha già un deployment `queued`/`in_progress`; i form di `/admin/deploy` disabilitano il pulsante al primo invio e la sezione *Configurazione* indica se il riconoscimento dell'auto-deploy è pronto (`uuid` nell'hook + `COOLIFY_API_TOKEN`).
### Documentation
* manuale operatori: riconoscimento dell'auto-deploy GitHub, nuova variabile `DEPLOY_AUTODEPLOY_GRACE_SECONDS` e troubleshooting del doppio deployment; README, `ARCHITETTURA.md` e `.env.example` aggiornati.
## [0.10.0](https://github.com/simograndi/taskman/compare/taskman-v0.9.0...taskman-v0.10.0) (2026-10-20)
### Features
* deduplicazione dell'hook di deploy Coolify: entro `DEPLOY_HOOK_DEDUPE_SECONDS` (default 60) un invio riuscito non viene ripetuto, così doppio click o retry non avviano due deploy.
* riepilogo sintetico *Stato ultimo deploy* in `/admin/deploy`: esito complessivo, conteggio OK/errori/saltati, timestamp dell'ultima esecuzione e ultima risposta HTTP dell'hook.
### Security
* isolamento del modulo Deploy in Produzione (`FLASK_ENV` diverso da `development`): voce di menu, badge e pulsanti di promozione non vengono renderizzati; le `GET /admin/deploy*` redirigono alla dashboard con un avviso e le `POST` rispondono `403`.
### Documentation
* manuale operatori aggiornato: pannello Deploy esclusivo dello Staging, deduplicazione del webhook e riepilogo dell'ultimo deploy; `.env.example` con `DEPLOY_HOOK_DEDUPE_SECONDS`.
## [0.9.0](https://github.com/simograndi/taskman/compare/taskman-v0.8.0...taskman-v0.9.0) (2026-10-20)
### Features
* pool DB resiliente Neon con Flask-SQLAlchemy e `.env` consolidato ([d690ed7](https://github.com/simograndi/taskman/commit/d690ed71f2dd75e612d0b66428281ac75a26254f))
### Bug Fixes
* promozione e deploy supportano `PROD_DATABASE_URL` oltre alle variabili `PROD_PG*` ([13096ec](https://github.com/simograndi/taskman/commit/13096ec33dafbb314a09d07fb1bf6f101a08dab6))
* favicon dinamica in `templates/base.html`: la scelta tra `img/favicon_staging.ico` e `img/favicon_prod.ico` avviene con una condizione Jinja su `config.get('FLASK_ENV')`, con `FLASK_ENV` sincronizzato nella configurazione Flask a ogni render; i due file `.ico` restano in `static/img/` e non producono 404.
### Documentation
- Nuovi manuali `docs/MANUALE_PUBBLICO.md` (utenti, ambienti e SEO) e `docs/MANUALE_OPERATORI_ADMIN.md` (promozione Staging → Produzione, webhook Coolify, isolamento SEO).
- CHANGELOG riordinato in una cronologia sequenziale da `0.4.4` in poi (`0.5.0`, `0.6.0`, `0.7.0`) e `VERSION` portato a `0.9.0`.
## [0.8.0](https://github.com/simograndi/taskman/compare/taskman-v0.7.0...taskman-v0.8.0) (2026-10-20)
### Features
* aggiungi protezione CSRF per le richieste POST ([d69b9ce](https://github.com/simograndi/taskman/commit/d69b9ceafcd0f359bba69333d27fc8f0f3141cf6))
* autenticazione Bearer del token API Coolify nell'hook di deploy ([a9b355a](https://github.com/simograndi/taskman/commit/a9b355a82e1149aad4a2d5d72337f38098af6c1e))
* blocco modifica su richieste prese in carico, completamento nominativi e avviso Nomi Modificati ([9c0aab6](https://github.com/simograndi/taskman/commit/9c0aab62f03ef6e00c184d36a9dd132dfbea75e2))
* configura modal debug e asset Eventix ([ab96429](https://github.com/simograndi/taskman/commit/ab96429fea1fad158f366e23089a027bbaa44064))
* elenco e gestione biglietti con allegati PDF e codici (solo admin) ([35e7d24](https://github.com/simograndi/taskman/commit/35e7d24db52672069466bdb193832aa581ac25b8))
* gestione SEO dinamica (robots.txt, sitemap.xml, X-Robots-Tag, canonical) ([51b3406](https://github.com/simograndi/taskman/commit/51b3406b89140d8814057fb9310ca211c88826c9))
* introduzione connection pool, compressione web, indici di performance e manuali funzionali aggiornati ([fbe4b47](https://github.com/simograndi/taskman/commit/fbe4b4776710022cc365885999748602f4679177))
* operazioni massive, e refactoring responsive PWA ([b358950](https://github.com/simograndi/taskman/commit/b35895077ef1783108ba1d1c1c500be7489e41a6))
* ricerca globale header e filtri live nelle viste di gestione ([1699a98](https://github.com/simograndi/taskman/commit/1699a985e70c80be62d411474477a03af9ec34ae))
* tracciamento nomi biglietti/pass con contatore e avviso duplicati per admin ([22eb410](https://github.com/simograndi/taskman/commit/22eb410977491ef55cde5c0ec6a8eb4ff1e08cef))
### Bug Fixes
* admin e simone mantengono ruolo admin + permesso superuser ([3e95b55](https://github.com/simograndi/taskman/commit/3e95b55133d8ffff2fc7c18c56c316f141c9fa29))
* appunti architettura e manuale per contatti multipli e nome-citta ([dab9dae](https://github.com/simograndi/taskman/commit/dab9dae8d41c93a5730ff3d8ed8c7becc4555a7c))
* cursor already closed in gestione eventi ([fc01b8b](https://github.com/simograndi/taskman/commit/fc01b8bf989bf0104f4649d0e4365140235e79cb))
* data evento nei risultati della ricerca globale ([a5b5848](https://github.com/simograndi/taskman/commit/a5b58487457683572432b977d1b5c0146d396343))
* delivery e new event, overview ([17a85af](https://github.com/simograndi/taskman/commit/17a85afa5e8fbc3ef95fd360d6b9a799edc2f204))
* deploy limitato al ruolo superuser (ex superadmin hardcoded) ([088f2d6](https://github.com/simograndi/taskman/commit/088f2d620d4e311c77e571d2a5d6812bd60f4196))
* deploy superuser mantiene permessi admin (role invariato) ([5683bc5](https://github.com/simograndi/taskman/commit/5683bc57f56cbafc4daf99b594ea1106b513c98c))
* disattiva debug Flask di default e proteggi l'avvio locale ([83baac2](https://github.com/simograndi/taskman/commit/83baac2a00f2efaa112752490c0f1a5aa60edbfb))
* elenchi ([e0168b4](https://github.com/simograndi/taskman/commit/e0168b43115b947f2aefe6ade4359ed5f56a0313))
* gestione e modifica richieste ([a08472c](https://github.com/simograndi/taskman/commit/a08472c9d3e2b4fe2cf2472c4f4f7e28ca35f94f))
* Gestione Utenti ([6352c6a](https://github.com/simograndi/taskman/commit/6352c6a28e81ad078f1ff2a22daa0597932a88c1))
* Heathcheck ([c0a2e23](https://github.com/simograndi/taskman/commit/c0a2e238568462b74b03b35a9713210e70e7d010))
* le modali di creazione rapida non chiudono piu il form evento ([72782c8](https://github.com/simograndi/taskman/commit/72782c895e13df13d8f40f3043e3bebe3d8db506))
* login, user, richieste ([9b4b6e9](https://github.com/simograndi/taskman/commit/9b4b6e9ba97fcd99f2b32695b0b19915d8415baf))
* Notifiche ([04e5b48](https://github.com/simograndi/taskman/commit/04e5b48da0434369ee4c4cc9f204a8d0723761b2))
* nuova richiesta ed altri bug ([074f062](https://github.com/simograndi/taskman/commit/074f062dcd3931911a0430e1841e1b560f8030db))
* organizzatori/eventi ([2963d91](https://github.com/simograndi/taskman/commit/2963d91275d950c3246d4df2340bdb1af91a5d06))
* piattaforma di vendita ([3a6dd72](https://github.com/simograndi/taskman/commit/3a6dd7291c44ae5956cae1f7bf0f3bcc216847bb))
* postimultipli e gestione ([316fa0a](https://github.com/simograndi/taskman/commit/316fa0a5306a4a81009438f333d28561d0860fc5))
* ricerca dinamica ([4c8e5cb](https://github.com/simograndi/taskman/commit/4c8e5cba8d88f4eed490ce3fb550ec4be9f7867d))
* ricerca e campi obbligatori ([8bf7932](https://github.com/simograndi/taskman/commit/8bf7932579d7642715dcaef2297509a865facb35))
* ricerca luoghi e artisti ([5da7e58](https://github.com/simograndi/taskman/commit/5da7e584ecb081f6783b1dacd42b32fc665920c6))
* rotte admin e ruolo effettivo per i superadmin, deploy separato dai dati ([1c50850](https://github.com/simograndi/taskman/commit/1c50850def429b80475186d4bbc3390e82480be5))
* senza nome ([d3607ca](https://github.com/simograndi/taskman/commit/d3607ca613898eba44454cfe7d7860d8a3c15d98))
* usa la strategia release-please simple per aggiornare VERSION e CHANGELOG ([f471436](https://github.com/simograndi/taskman/commit/f4714360891fba08632e0cdd6dd19646a0853f9a))
* **Hook di deploy Coolify: risolto l'errore HTTP 401 Unauthorized**. La chiamata a `PROD_DEPLOY_HOOK_URL` usa `requests.post` con l'header `Authorization: Bearer <COOLIFY_API_TOKEN>` e `Content-Type: application/json`; la risposta viene verificata (HTTP 200/201 = deploy avviato, 401/403 = token non valido o non autorizzato, altri status = errore) e ogni esito, compresi gli errori di rete, è riportato con un messaggio descrittivo nel backoffice senza eccezioni non gestite e senza esporre token o URL.
## [0.7.0] - 2026-10-20
### Added
- **Deploy codice separato dai dati**: `POST /admin/deploy/run` esegue solo migrazioni schema prod, merge GitHub `develop` → `main` e hook (mai dati). Promozione dati sempre selettiva: per singolo record (`publish`/`remove`/`demo`) o bulk per entità (`POST /admin/deploy/data` → `promotion.sync_entities`), mai utenti/richieste/biglietti/note/notifiche/impostazioni.
- **Gestione per singolo record** (eventi, luoghi, organizzatori): pulsanti *Pubblica / Aggiorna in Produzione* e *Rimuovi dalla Produzione*, flag **demo** (esclusi dalla produzione) e stato `PENDING_DELETION` (rimozione applicata subito se la produzione è raggiungibile, altrimenti marcata in attesa), con badge *Demo*, *In produzione* e *Rimozione in attesa*. Nuove colonne `is_demo` e `sync_status` (e `sync_uid` sugli eventi).
### Fixed
- **Rotte admin e ruolo per i superadmin**: `/events`, `/locations` e `/organizers` (e le altre rotte admin) tornano a funzionare per `@admin` e `@simone`: i superadmin hanno ruolo `admin` + flag `is_superuser`, la sessione ne normalizza il ruolo effettivo a `admin` e i template usano il ruolo effettivo invece del solo `session['role']` (menu admin completo, rotte e badge corretti). Il menu mostra il badge scudo **Superadmin** e la lista utenti la colonna di stato.
- **Fix 500 su `/events`, `/locations`, `/organizers`**: `record_sync_info` non solleva mai 500 (catch-all + rollback protetto), `get_db_connection()` ricrea connessioni chiuse/rotte del pool e le viste non chiudono più la connessione prima del render (rilascio al teardown).
## [0.6.0] - 2026-10-19
### Added
- **Gestione SEO dinamica**: rotta `/robots.txt` che in produzione consente l'indicizzazione pubblica (`Allow: /`, blocca `/admin/`, `/operator/`, `/api/`, dichiara la sitemap) e in sviluppo blocca tutto (`Disallow: /`), con mimetype `text/plain`.
- Header HTTP `X-Robots-Tag: noindex, nofollow, noarchive` automatico in ambiente di sviluppo (`FLASK_ENV=development`) tramite `@app.after_request`.
- Meta tag `<meta name="robots">` dinamico e tag `<link rel="canonical">` sempre puntante al dominio ufficiale di produzione (`PROD_DOMAIN`) in `templates/base.html`.
- Rotta `/sitemap.xml` dinamica (mimetype `application/xml`): in produzione espone le pagine pubbliche, in sviluppo restituisce HTTP 404.
- Variabile d'ambiente `PROD_DOMAIN` (default `eventix.work`) per URL canonici e sitemap; documentata in `.env.example`.
- Test `tests/check_seo.py` per `/robots.txt`, `/sitemap.xml`, `X-Robots-Tag`, meta robots e canonical in entrambi gli ambienti.
- Nuova richiesta senza nominativi: i **nomi dei partecipanti sono facoltativi** all'inserimento (e nella modifica completa admin). La richiesta viene salvata anche senza nominativi con un avviso giallo; admin ed editor ricevono una notifica interna "Richiesta senza nominativi" (messaggio **URGENTE** se all'evento mancano meno di 5 giorni). Le richieste senza nominativi e con evento a **meno di 5 giorni** sono evidenziate con un alert rosso in dashboard, *Gestisci richiesta* e *Modifica richiesta*, con badge di richiamo negli elenchi.
- **Prompt di impegno sui nominativi (ruolo utente)**: inviando una nuova richiesta senza nominativi l'utente vede la finestra *Nominativi da comunicare* con la scadenza (5 giorni prima dell'evento) e deve spuntare *Accetto l'impegno* per procedere (l'invio è bloccato anche lato server); l'impegno è registrato sulla richiesta. Il richiedente riceve l'email di conferma con la scadenza e lo staff viene avvisato dell'impegno preso. Admin ed editor inviano senza prompt.
- **Promemoria automatici per i nominativi mancanti**: avvicinandosi la scadenza, richiedente e staff ricevono una email di promemoria e una notifica in campanella per le richieste ancora prive di nominativi; l'invio è idempotente (una sola volta per richiesta).
- **Richiesta presa in carico e completamento nominativi**: una richiesta è "presa in carico" quando almeno un biglietto/pass è *Emesso* oppure lo staff ha portato lo stato oltre *Ricevuta*. Da allora il richiedente non può più modificarla né eliminarla (403/404) e la pagina diventa **Richiedi una modifica**; può solo completare le schede senza nome o cognome (sezione *Completa i nominativi mancanti*, con telefono/email) oppure inviare una richiesta di modifica dal diario note.
- **Avviso "Nomi Modificati"**: il completamento dei nominativi attiva il nuovo flag `requests.names_modified`, mostra badge negli elenchi e alert in *Gestisci richiesta*/*Modifica richiesta* e riallinea i biglietti in `tickets` dei nominativi toccati, conservando gli allegati dei nomi invariati. L'avviso si azzera salvando la richiesta dalla gestione.
- **Eliminazione richiesta**: nuovo pulsante *Elimina* (con conferma) nella pagina di modifica e negli elenchi dashboard/evento. Gli admin eliminano qualsiasi richiesta, gli utenti solo le proprie non ancora prese in carico; la cancellazione rimuove a cascata partecipanti, diario note e biglietti. Il redirect accetta solo un `return_to` interno (anti-open-redirect).
### Changed
- **Debug Flask sicuro per default**: `FLASK_DEBUG` ha default `false` e l'avvio diretto con debug attivo e `HOST` non locale (es. `0.0.0.0`) viene rifiutato con un errore esplicito, per non esporre in rete il debugger Werkzeug; `python app.py` usa `HOST` con default `127.0.0.1` e `PORT` invariato. Variabili documentate in `README.md` e `.env.example`.
### Fixed
- Richieste senza nominativi: `add_request` e `update_request_full_admin` non bloccano più il salvataggio quando nome o cognome dei partecipanti non sono compilati; il referente scelto fra i partecipanti continua a richiedere nome, cognome e un recapito valido.
### Security
- **Protezione CSRF su tutte le azioni di modifica**: ogni richiesta `POST`/`PUT`/`PATCH`/`DELETE` deve inviare un token legato alla sessione — campo nascosto in tutti i form, header `X-CSRF-Token` per le richieste in background, campo `csrf_token` nel body JSON. Senza token valido la richiesta viene respinta prima di toccare il database o inviare email: `400 {"ok": false}` per gli endpoint `/api/*`, avviso e ritorno a una pagina sicura per le pagine normali. Il token è stabile per la durata della sessione, quindi i form aperti a lungo restano validi; accesso (`/login`) e primo inserimento password restano esenti in questa fase.
- **Cookie di sessione più protetti**: `SESSION_COOKIE_HTTPONLY=True` e `SESSION_COOKIE_SAMESITE="Lax"`; `SESSION_COOKIE_SECURE` non viene attivato automaticamente perché richiede HTTPS.
## [0.5.0] - 2026-10-11
### Added
- **Modulo di promozione dinamica staging → produzione** (solo superadmin): nuova pagina `/admin/deploy` (voce **Deploy** nel menu) che applica le migrazioni pendenti al DB di produzione, esegue il merge GitHub `develop` → `main` (se `GITHUB_TOKEN` e `GITHUB_REPOSITORY` sono configurati) e invoca `PROD_DEPLOY_HOOK_URL` per aggiornare il container. Senza variabili di produzione i passi vengono saltati con un avviso, senza errori HTTP 500; un errore su un passo interrompe quelli successivi. La sincronizzazione dei dati è separata e selettiva (vedi *Deploy codice separato dai dati*).
- Doppia connessione DB: variabili `PROD_PGHOST`, `PROD_PGDATABASE`, `PROD_PGUSER`, `PROD_PGPASSWORD`, `PROD_PGPORT`, `PROD_PGSSLMODE` (e opzionale `PROD_PGCHANNELBINDING`) per la produzione; supportato anche `PGPORT` per lo staging. Il deploy è rifiutato se produzione e staging puntano allo stesso database.
- **Sistema ruoli superadmin**: flag `users.is_superuser` che eredita tutti i permessi `admin` più il deploy; `initialize_database()` imposta ruolo `admin` + `is_superuser = TRUE` per `@admin` e `@simone` (incluso il legacy `role = 'superuser'`). La sessione normalizza i superadmin a ruolo effettivo `admin` (login, set-password, refresh con init schema anticipato), così rotte e menu admin funzionano; badge scudo **Superadmin** in header e lista utenti; deploy e promozione riservati ai superadmin (`@superuser_required`, 403 per gli altri).
- **Badge ambiente e favicon dinamica**: in base a `FLASK_ENV` l'interfaccia mostra *Staging Mode* (`development`) oppure *Official* e carica `favicon_staging.ico` o `favicon_prod.ico`.
- Test `tests/check_promotion.py` (accessi, fallback sicuro, merge/hook simulati, badge/favicon, perimetro delle tabelle sincronizzate).
- Elenco e gestione biglietti (solo admin): nuova voce **Biglietti** nel menu con tutti i nominativi tracciati — evento e data, richiedente, stato richiesta, stati biglietto/pass e zona, badge allegato, registrazione e il contatore "N richieste" sotto al nominativo — con filtro live e scheda **Dettaglio** con link a *Gestisci richiesta*; dalla scheda si aggiornano **link PDF** e **codice biglietto** (il caricamento file PDF è predisposto ma al momento disabilitato) e la tipologia di invio dell'evento è mostrata come riferimento. Il riallineamento con la richiesta ora conserva gli allegati: risalvare non azzera più PDF e codici inseriti.
- Creazione rapida "in overlay" di Luogo e Organizzatore dal form evento (nuovo e modifica): i pulsanti **+** aprono una modale che salva **senza ricaricare la pagina** tramite i nuovi endpoint JSON `POST /api/locations` e `POST /api/organizers`; il record creato viene aggiunto e selezionato automaticamente nella tendina e i dati già inseriti nell'evento restano compilati.
### Changed
- Recapiti del referente esterno riusati senza doppio inserimento: se il referente/richiedente esterno coincide (confronto normalizzato di nome e cognome) con un partecipante, i recapiti già indicati vengono copiati automaticamente sui campi vuoti della scheda partecipante, sia lato server sia in tempo reale nei form.
## [0.4.4] - 2026-10-05
### Changed
- Eventi con più contatti organizzatore: selettori ripetibili e ricercabili, senza duplicati, filtrati per organizzatore. Il cambio organizzatore azzera le selezioni; modifica e duplicazione conservano l'ordine. Elenco e dettaglio mostrano tutti i contatti (con recapiti nel dettaglio).
- Etichette evento uniformate a **Nome — Città** in elenchi, dashboard, richieste e suggerimenti di ricerca; senza città rimane il solo nome.
- Inizializzazione database: tabella `event_organizer_contacts` e recupero idempotente dei contatti legacy validi, mantenendo il primo contatto in `events.organizer_contact_id` per compatibilità.
### Fixed
- Notifiche (alert) rivisti: risolto il bug `psycopg2.InterfaceError: cursor already closed` in gestione richiesta (il controllo "evento passato" riusava il cursore dopo `cur.close()`, quindi la notifica di emissione non partiva mai e scattavano retry/500); confronto date unificato su `datetime.now()`; anti-duplicato interno (stessa notifica allo stesso utente entro 10 minuti, un solo inserimento per utente anche se i ruoli si sovrappongono) e anti-toast-doppio nel frontend (stessa pagina + altre tab via `localStorage`): niente più "4 notifiche uguali".
- Alert visivi coerenti: giorni rimanenti calcolati a giorno (`event.date - oggi`), non a ore — "Domani" resta domani fino a mezzanotte, "Oggi" solo il giorno stesso, evento passato marchiato **Scaduto** (mai "Oggi"/giorni negativi); richieste da gestire con badge graduato (grigio da 1 g, giallo da 3 g) e riga `table-warning` da 1 g; elenco eventi con badge **Scaduto · data** anche nel filtro "Tutti".
### Added
- Tracciamento nomi richiesti (visibile **solo agli admin**): nuova tabella `tickets` che registra ogni nominativo per cui vengono chiesti biglietti/pass (una riga per richiesta e nome normalizzato, con i campi riservati `pdf_url`/`ticket_code` predisposti ma non ancora usati per allegare PDF o codice). Se un admin immette un nome già presente riceve un **avviso giallo** ("Nome già richiesto in precedenza…") con il numero di richieste precedenti e il contatore viene incrementato; in *Gestisci richiesta* e nella *Modifica richiesta completa* sotto al nome compare in piccolo **quante richieste di biglietti/pass sono state fatte** per quella persona. Mentre digiti nome e cognome nei form compaiono avvisi a comparsa con i nomi già richiesti o simili (`GET /api/tickets/check`, solo admin); i flash ora distinguono il colore per categoria (giallo per gli avvisi, rosso per gli errori).
- Ricerca globale nell'header (`GET /api/search?q=`): campo centrale con risultati live raggruppati (Eventi, Richieste, Luoghi, Organizzatori, Utenti) e link diretti; lo scope rispetta il ruolo (gli user vedono solo eventi attivi futuri e proprie richieste). I risultati di eventi e richieste mostrano anche la data dell'evento (gg/mm/aaaa hh:mm) per distinguere gli omonimi.
- Filtro dinamico in tempo reale in ogni vista di gestione (richieste in dashboard e dettaglio evento, eventi, luoghi, organizzatori, utenti): campo al centro della barra titolo, conteggio “N totali” aggiornato al volo e messaggio di nessun risultato; i link globali a luoghi/organizzatori/utenti precompilano il filtro via `?q=`.
- Gestione richiesta: il blocco di aggiornamento in massa è ora **"Applica a selezione"**: ogni partecipante ha un flag di selezione con casella **"Tutti"** nell'intestazione della tabella; gli stati biglietti/pass (e la nuova **zona biglietto**) si applicano solo ai selezionati, con avviso se nessuno è spuntato.
- Gestione richiesta: quando un biglietto viene messo in stato **Emesso** compare la scelta della **tipologia di posto** (zona, es. Platea, Tribuna numerata) presa dalla scheda evento, con posti disponibili indicati; la zona è salvata per partecipante (`request_participants.ticket_zone`, conservata anche nelle modifiche complete admin e azzerata se il biglietto non è più emesso). Applicabile anche in massa ai selezionati.
- Dettaglio evento (admin/editor): **overview sempre visibile** con biglietti totali, disponibilità residua (colorata a semaforo), richieste da evadere e numero di zone ripartite.
- Eventi: **Zone e biglietti multipli** (`events.ticket_zones`, es. Posto unico, Platea, Tribuna numerata): nel form nuovo/modifica evento ogni riga è *zona + posti*; scegli una zona e compare automaticamente una nuova riga, senza duplicati. Il default è **"Posto unico"**. La **somma dei posti delle zone deve coincidere con i posti totali** (che fanno fede per semaforo e disponibilità): in caso di scostamento compare un avviso con le azioni **"Aggiorna totale"** (allinea il totale alla somma) e **"Rivedi posti"** (resta da correggere, l'invio è bloccato finché non coincidono); il server valida di nuovo e avvisa con un flash. La **capienza del luogo è solo un riferimento visualizzato, mai compilata in automatico**. Zone e posti sono mostrati nel dettaglio evento; la duplicazione evento li copia. Elenco zone e **sinonimi** (righe `Canonico = alias1, alias2`, usati per normalizzare i nomi in fase di importazione) configurabili in *Impostazioni* (`ticket_zones_list`, `ticket_zone_synonyms`).
- Gestione utenti: il form "Nuovo utente" (solo admin) include i campi **Telefono** e il flag **Richiesta pass** (gli admin sono sempre abilitati e l'elenco mostra telefono e permesso pass di ogni utente); **solo gli admin gestiscono i pass**: nella gestione richiesta gli altri ruoli vedono categoria e stato pass in sola lettura (niente flag, selettori o applicazione in massa) e il server ignora comunque i campi pass eventualmente inviati dal form.
- Gestione utenti rifatta: l'elenco `/users` è ora una tabella di sola lettura (anagrafica, contatti, ruolo, permesso pass) e ogni persona ha una pagina di modifica dedicata `/users/<id>/edit`; gli admin gestiscono username, ruolo, permesso pass e possono **reimpostare la password**, gli editor modificano solo anagrafica e contatti.
- Profilo personale `/profilo` per tutti i ruoli (raggiungibile dal menu del proprio nome): dati personali e avatar, cambio password con verifica della password attuale e **preferenze di notifica individuali** (nuove colonne `users.notify_email` e `users.notify_browser`): disattivando le email non si ricevono più le notifiche di sistema, disattivando gli avvisi a comparsa non compaiono più i toast (campanella e contatore restano attivi).
- Eventi: campo **Piattaforme di vendita** (`events.sales_platform`, es. Botteghino, Sito Web Ufficiale, TicketOne, Vivaticket), **una o più per evento**: alla creazione e in modifica evento una nuova riga di selezione compare automaticamente dopo la scelta, senza duplicati. Elenco configurabile `sales_channels_list` nelle Impostazioni; mostrato nel dettaglio evento e nella pagina di modifica richiesta.
- Modifica richiesta (admin): il richiedente registrato si seleziona con un combobox ricercabile con voce "Esterno"; se il richiedente e indicato come referente, i recapiti (telefono/email) vengono compilati automaticamente dai dati utente, con fallback lato server.
- Impostazioni: nuovo elenco "Piattaforme di vendita" (`sales_channels_list`) modificabile dagli admin.
- Eventi: **Artista**, **Città** e **Luogo** (testo libero di fallback) funzionano come gli altri campi di ricerca: mentre digiti propongono gli artisti già usati negli altri eventi, le città già usate e i nomi dei luoghi esistenti, per evitare doppioni e varianti dello stesso nome; resta possibile inserire un valore nuovo.
- Eventi: gli admin possono **duplicare** un evento dal pulsante "Duplica" in `/events` (`POST /events/<id>/duplicate`): copia senza richieste (nome + " (copia)", luogo, organizzatore, consegna, piattaforme e responsabili); la copia nasce non attiva da verificare/attivare.
## [0.4.3] - 2026-09-15
### Fixed
- Gestione richiesta: sistemato il layout della tabella partecipanti — niente più campi sovrapposti o tagliati: la pagina usa tutta la larghezza disponibile, ogni colonna ha una larghezza minima (Partecipante, Contatti, Biglietto, Pass), i contatti sono impilati senza schiacciare la riga, i select ricercabili compatti non vengono più coperti dalle icone di freccia e di reset e la tabella scorre in orizzontale sui display stretti. Il blocco "Applica a selezione" non comprime più select e pulsante (vanno a capo) e passa a tre colonne solo da schermi `lg`.
### Added
- Gestione richiesta (admin/editor): **disponibilità residua visibile** durante la selezione e l'assegnazione del posto. In cima alla pagina i badge posti totali / richiesti / disponibili (a semaforo come nel dettaglio evento) e, per gli eventi con più zone, i **posti liberi per zona** con la zona esaurita evidenziata. In ogni riga la tendina della tipologia di posto mostra i posti liberi della zona e, sotto la scelta, compare l'avviso "Posti liberi in …: N su M" (oppure "Zona esaurita"), aggiornato al volo quando si cambia stato biglietto o zona; anche il selettore in massa "Zona biglietto dei selezionati" riporta i posti liberi di ogni zona.
## [0.4.2] - 2026-09-14
### Fixed
- Login: il nome utente non è più sensibile alle maiuscole/minuscole — accetta ad esempio `Admin`, `ADMIN` o `aDmin` per l'utente registrato come `admin` (la password resta sensibile alle maiuscole).
- Homepage e filtro richieste: corretto il filtro "Archiviate", che passava `status=Archiviate` invece del valore realmente salvato nel database (`Archiviata`), quindi la selezione non mostrava alcuna richiesta anche quando una richiesta archiviata esisteva.
- Homepage (admin/editor): aggiunto il pulsante **Archivia** accanto alle richieste concluse (evento già passato o già archiviate) per portarle direttamente a stato `Archiviata`.
- Gestione richiesta: l'archiviazione (o l'aggiornamento) di una richiesta per un evento **già passato** non invia più nessuna notifica (né email né notifica interna di emissione biglietti/pass).
- Nuova richiesta (admin): selezionando un richiedente dall'elenco utenti, il nominativo e i recapiti (telefono/email) del referente (se il destinatario è il richiedente) vengono compilati automaticamente; inoltre il form non richiede più il reinserimento dei recapiti del richiedente esterno quando questi sono già indicati nella sezione Richiedente.
- Nuova richiesta (admin): corretto il salvataggio del richiedente selezionato dall'elenco utenti: prima il nome veniva copiato nel campo del richiedente esterno e il server lo trattava come esterno perdendo il collegamento all'utente; ora `requested_by` ha priorità sul nome, quindi il richiedente registrato viene associato correttamente all'utente e i recapiti del referente sono presi dal suo profilo.
- Nuova richiesta (admin): corretta la compilazione/ripristino dei dati del primo partecipante quando la validazione del form riporta di nuovo i campi partecipanti dopo un errore.
- Homepage e elenco eventi: precisato che la home mostra gli eventi futuri; un evento futuro prossimo (es. "Ligabue - Jesolo" del 12/09/2026) appare normale e non grigio perché non ancora scaduto; lo sfondo grigio/evidenziazione per scaduti vale sugli elenchi completi o quando filtrati per eventi passati.
- Gestione eventi e modifica evento: risolto l'errore `psycopg2.InterfaceError: cursor already closed` (le impostazioni venivano lette dopo la chiusura del cursore).
- Modifica richiesta: rimosso l'`id` duplicato del campo Note nel form completo.
- Notifiche: corrette le regole di invio — l'emissione di biglietti/pass notifica l'utente richiedente (o il referente invio per richiedenti esterni), le nuove note notificano anche l'utente richiedente oltre ad admin/editor, l'autore non riceve la notifica della propria azione e le richieste di modifica su biglietti emessi avvisano admin/editor.
- Gestione luoghi: corretto il disallineamento tra query e template — la tabella mostrava città/capienza/contatti nei campi sbagliati e i pulsanti "Sito web", "Mappa" e "Planimetria" puntavano a campi diversi; nei form di creazione e modifica manca la **Città** (che veniva azzerata a ogni salvataggio) e la tipologia selezionata non risultava mai corretta: ora campi e indici sono allineati e l'ordine è Nome, Indirizzo, Città, Tipologia, Capienza, Sito web, Mappa, Planimetria, Contatto, Email, Telefono.
- Dashboard: le richieste concluse (evento già passato o archiviate) sono spostate in fondo all'elenco ed evidenziate con sfondo grigio, come per gli eventi passati.
- Elenco eventi: con il filtro "Tutti" gli eventi già terminati (data passata) sono spostati in fondo all'elenco ed evidenziati con sfondo grigio, in linea con le richieste concluse in dashboard.
## [0.4.1] - 2026-09-09
### Added
- Eventi: tipologia di invio biglietti (`events.delivery_type`: invio digitale, invio cartaceo, ritiro in cassa accrediti, codice, altro) con note aggiuntive libere (`events.delivery_notes`), selezionabile alla creazione e modificabile dagli admin; mostrata nel dettaglio evento e nella creazione richiesta quando si seleziona l'evento.
- Gestione eventi: il form di creazione evento non è più sempre visibile in alto ma si apre da un pulsante "Nuovo evento" in una finestra modale.
- Gestione richiesta: aggiornamento in massa degli stati dei biglietti (e dei pass) di tutti i partecipanti con un solo clic.
- Ottimizzazione layout mobile: page-heading impilabile, tabelle e form più compatti su smartphone.
## [0.4.0] - 2026-09-09
### Added
- Richieste: scelta del destinatario di biglietti e pass (richiedente o uno dei partecipanti referente). Il referente deve avere nome, cognome e almeno un recapito validato (telefono o email). Possibile scegliere come richiedente anche utenti admin/editor, non solo user.
- Note delle richieste salvate come diario/log (`request_notes`): ogni inserimento viene aggiunto con autore, ruolo e data. Gli utenti modificano le richieste non emesse; dopo l'emissione inviano una richiesta di modifica agli amministratori.
- Modifica completa della richiesta riservata agli admin: richiedente (anche esterno), radio/cliente, quantita, partecipanti, destinatario invio.
- Eliminazione eventi e luoghi (solo admin, con conferma): la cancellazione e bloccata se esistono richieste/collegamenti.
- Luoghi: campi edit/delete ripristinati con piano di modifica completo (anche link mappa dedicato).
- PWA: `manifest.webmanifest`, icone dedicate e meta tag; il titolo delle pagine ora e `Eventix | pagina`.
### Fixed
- Pulsanti modifica/elimina uniformati (dimensioni identiche) su organizzatori, eventi e luoghi.
- "Apri mappa" dell'evento usa il link mappa del luogo oppure Google Maps dall'indirizzo (prima inviava al sito web).
- Impaginazione lista eventi e form richiesta su smartphone (layout non piu sovrapposto).
## [0.3.2] - 2026-09-09
### Fixed
- Sistemata la ricerca dinamica: i campi ricerca/combo non visualizzano più tutti i record sovrapposti, ma si comportano con una ricerca dinamica con autocomplete (ricerca per sottostringa, anche parte di una parola all'interno della frase). Aggiunto pulsante freccia per visualizzare tutte le opzioni disponibili. Applicato a tutti i campi di questo tipo nell'app.
## [0.3.1] - 2026-09-02
### Fixed
- Risolto il conflitto nell'uso contemporaneo dello stesso file di versione/changelog e verificata la correttezza complessiva delle funzionalità e dei test.
## [0.3.0] - 2026-09-02
### Fixed
- Corretta la gestione dei contatti dell'organizzatore nella creazione e modifica degli eventi, garantendo che vengano mostrati e associati correttamente solo se l'organizzatore è selezionato.
### Added
- Gestione anagrafiche organizzatori e contatti associabili agli eventi.
- Aggiornamento dei luoghi registrati con il link al sito web in sostituzione del link mappa.
## [0.2.0] - 2026-09-01
### Added
- Menu operativo permanente per ogni ruolo.
- Gestione eventi, partecipanti, disponibilita e impostazioni.
- Impersonificazione utenti riservata agli amministratori.
- Credits con dati sviluppatore e cronologia delle versioni.
- Anagrafiche organizzatori, relativi contatti e aggiornamento gestione luoghi con sito web.
## [0.1.0] - 2026-09-01
### Added
- Gestione ruoli, eventi e richieste.
- Area amministrativa per utenti ed eventi.