Changelog
Tutte le modifiche rilevanti a BlueGem CRM, versione per versione. Il formato segue Keep a Changelog e il progetto adotta il Semantic Versioning: le modifiche che cambiano il comportamento di un'istanza esistente sono sempre segnalate in una sezione dedicata.
Non rilasciatoIn arrivo nella prossima versione
Le voci di questa sezione sono già completate e verificate, ma non fanno ancora parte di una versione pubblicata: arriveranno con la prossima release.
Aggiunto
- Soglia sull'advisor «Query più costose» (Gestione DB): campo in
millisecondi e preset rapidi (100 ms / 500 ms / 1 s / 2 s) per mostrare solo le query
oltre una certa latenza media per esecuzione, mantenendo l'ordinamento
per costo totale. Nuovo parametro opzionale
minMssuGET /admin/db/slow-queries, documentato in OpenAPI e limitato a 600 000 ms (10 minuti).
Modificato
- Finestre temporali di KPI e report ora indicizzabili. Il filtro di
periodo non casta più la colonna data (
created_at::date): i limiti sono già allineati a mezzanotte, quindi il confronto resta identico a granularità giorno ma diventa sargable. Su 2 milioni di record questo toglie da solo circa 1,3 s di soli cast per query. - Nuovo indice parziale
idx_custom_records_module_created_activesucustom_records (module_key, created_at) WHERE is_deleted = false: i KPI con periodo leggono solo le righe della finestra invece dell'intera tabella (misurato: da scansione completa a circa 0,1 ms quando la finestra è selettiva). Migration reversibile.
Corretto
- Mappa mondiale vuota. L'aggregazione dei grafici traduce le chiavi
picklist nelle etichette leggibili, ma la mappa aggancia i centroidi ai
codici ISO-2: riceveva «Italia» invece di «it» e non trovava alcun
paese.
aggregateByFieldaccetta oralabelize: falseper i consumatori che hanno bisogno delle chiavi grezze. - Grafico a torta affollato. Con poche fette venivano mostrate sia le etichette per-fetta sia la legenda: ridondante, e su card strette la legenda finiva sotto l'etichetta della fetta in basso. Ora legenda ed etichette si escludono a vicenda.
- Numero della scheda KPI tagliato. Il valore usava un troncamento con
overflow: hiddenche rasava gli apici del glifo: il numero non viene più ritagliato in verticale.
2026-07-26Versione 2.0.0
Il CRM gira ora su un backend unico scritto in Go, distribuito come binario compilato. Il vecchio backend Node/Express e' stato ritirato.
Cosa cambia per chi installa
- Sul server non serve piu' alcun runtime: niente Node, niente dipendenze da installare. Si copia l'artefatto e si lancia un comando.
- Messa in servizio in circa un minuto e mezzo da macchina nuova, misurata e documentata fase per fase.
- Sul server non finisce codice sorgente dell'applicazione: solo il binario. Il frontend resta in chiaro, perche' gira nel browser.
Cosa cambia nel comportamento
- L'import CSV e' piu' severo: i file malformati vengono rifiutati riga per riga con un errore esplicito, invece di essere accettati in silenzio.
- I workflow in bozza non si eseguono: vanno pubblicati, oppure provati con la simulazione.
- Diverse operazioni che prima non lasciavano traccia (team, impostazioni, aggiornamenti in blocco) ora sono registrate nell'audit.
- Le password usano un algoritmo di hashing piu' robusto: al primo aggiornamento vanno reimpostate.
2026-07-16Versione 1.3.0
Release di funzionalità e di sicurezza: oltre al redesign «Aurora» e alle nuove viste, chiude i rilievi di un audit completo di flusso, sicurezza e compliance. Contiene modifiche di comportamento: vedi la sezione dedicata in fondo alla versione.
Aggiunto
- Vista bacheca (Kanban) sulla lista modulo (drag-and-drop di stato).
- Tab dinamiche del dettaglio record + pannello admin a matrice.
- Tab Email nel dettaglio record (invio/ricezione sul record).
- Script di setup separati app/db e provisioning Linux
(
scripts/ops/setup-all|app|db.sh). - Redesign UI «Aurora» (design system, tema scuro) + tooling di backup GFS e restore.
- CI (GitHub Actions) sui gate del progetto; ESLint.
Sicurezza
- Workflow: fine dell'esecuzione con privilegi di sistema. Le azioni che
scrivono (
update_field,create_record,create_task,assign_record) non usano piùroleNames: ['admin']cablato: girano con i ruoli reali dell'autore del workflow e applicano permessi di modulo e ACL di campo. Un titolare diworkflows:managenon può più, tramite un workflow, scrivere o riassegnare ciò che non potrebbe toccare direttamente (la gerarchia di assegnazione è ora davvero rispettata). - Dry-run candidati: niente più oracolo di lettura.
POST /workflows/dry-run/candidatesnon esegue piùSELECT *senza filtri: richiede il permesso di lettura sul modulo (403 se negato) e compone lo scope in SQL; le condizioni fornite dal chiamante vengono valutate solo su record che potrebbe già leggere. - Merge: chiuso un IDOR.
POST /merge/undoeGET /merge/historyapplicano ora lo scope effettivo e rispondono 404 sui record fuori scope (anti-disclosure), invece di operare su qualunquemergeIdenumerabile e di esporre i nomi dei record fusi da terzi. - Reset password da admin: revoca le sessioni. Il reset amministrativo allinea il comportamento agli altri due percorsi di scrittura password: revoca i refresh token attivi e azzera il lockout. Un token rubato non sopravvive più alla remediation.
- Token di reset fuori dai log. L'access log e l'error handler registrano
ora solo il path, mai la query string: il token di
/reset-password?token=…(unica copia in chiaro esistente) non finisce più nei log. - Rate limit effettivo su
/auth/forgot-password. Nuovo limiter che conta anche le risposte 200 (l'endpoint risponde sempre 200 per non consentire enumerazione, quindi il limiter precedente, che contava solo i fallimenti, non scattava mai). Chiude il flood di email di reset e il reset-DoS. - MFA fail-closed. L'attivazione dell'MFA senza
CONNECTIONS_ENC_KEYnon salva più il segreto TOTP in chiaro: rifiuta con un errore esplicito, come già facevano tutti gli altri percorsi che trattano segreti. - Codici di recupero MFA robusti. Da 40 bit con SHA-256 non salato a 128 bit con scrypt salato (stesso schema delle password, confronto a tempo costante). I codici già emessi restano validi (verifica legacy mantenuta).
- Escape XSS su sink che interpolavano valori non filtrati: etichette/icone dei moduli e titoli dei gruppi nella sidebar (renderizzata su ogni pagina), etichette del gestore picklist.
- Oracolo di esistenza chiuso sull'import. Il match per
matchFielddell'import su moduli custom applica ora lo scope: non è più possibile dedurre l'esistenza di un record fuori dal proprio scope dal report di import.
Corretto
- Conversione lead: i workflow non scattavano. La conversione crea
account, contatto e (opzionale) trattativa e converte il lead senza emettere alcun
evento: i workflow
on_create/on_updatesui record nati dal funnel non partivano mai. Ora gli eventi vengono emessi dopo il COMMIT. - Import CSV su moduli custom: eventi e cronologia assenti. L'import scriveva direttamente sul repository, saltando il dispatch degli eventi e la cronologia record (mentre l'import sui moduli base li produceva). Allineato.
- Import CSV su moduli custom: progressivi non assegnati. Gli autonumber, esentati dal controllo di obbligatorietà perché "assegnati alla creazione", non venivano assegnati dall'import: record con identificativo obbligatorio vuoto. Inoltre, importando valori storici espliciti il contatore non avanzava e la creazione successiva da UI generava un duplicato silenzioso: il contatore viene ora riconciliato a max+1.
- Cronologia dei lead assente. L'aggiornamento dei lead non scriveva la
cronologia (unico modulo core a non farlo):
GET /leads/:id/historyrispondeva sempre vuoto. - Doppia emissione fattura. Il controllo su
invoice_refera una race (TOCTOU) che copriva più round-trip di rete verso il provider: due richieste concorrenti potevano creare due documenti reali, con il secondo che orfanava il primo. Introdotto un claim atomico sulla riga della trattativa; il perdente non chiama mai il provider e un errore del provider rilascia il claim (trattativa ri-emettibile). - Emissione che riportava successo senza scrivere. Il collegamento locale della fattura non verificava le righe aggiornate: se la trattativa veniva cancellata durante la chiamata al provider, l'utente vedeva "Fatturato" mentre il documento restava scollegato. Ora è un errore esplicito e tracciato.
- Merge: ROLLBACK dopo COMMIT. Un errore nel lavoro post-commit annullava una transazione già confermata, restituendo 500 su un merge di fatto avvenuto e non più annullabile. La riga di undo è ora scritta dentro la transazione (merge committato se e solo se undo possibile) e il post-commit non può più farla fallire.
- Merge: corrispondenza email persa. Le email collegate al record assorbito non venivano ripuntate al master e sparivano da entrambi i record.
- Merge: doppio undo. L'annullamento è ora idempotente sotto concorrenza
(
FOR UPDATE+ guardiaundone = FALSE). - Pagina Diagnostica senza navigazione. Era l'unica pagina con il markup della sidebar a non caricare lo script di navigazione: footer di navigazione vuoto e logout non funzionante.
- Link morti nelle email ricevute. L'iframe del corpo email era in sandbox completa (blocca i popup) pur forzando l'apertura in nuova scheda: ogni link era inerte, senza feedback.
- Tema non applicato su due pagine. La gestione utenti e l'editor moduli non sincronizzavano la preferenza tema: su un browser nuovo restavano in chiaro mentre il resto dell'app seguiva la preferenza salvata.
- Schema
crmin produzione + robustezza degli script di setup. - Bump
morgan1.10.1 → 1.11.0 (chiude una vulnerabilità segnalata danpm audit). - Diagnostica: query per tipologia (app + worker).
Modifiche di comportamento
Queste modifiche cambiano il comportamento di installazioni esistenti: leggile prima di aggiornare alla 1.3.0.
- L'MFA richiede
CONNECTIONS_ENC_KEY. Le installazioni che usano l'MFA senza aver configurato la chiave di cifratura non possono più completare l'attivazione:POST /auth/mfa/setuprisponde 422. Impostare la chiave prima di aggiornare. - I workflow di autori non-admin possono ora fallire. Se un workflow è stato creato da un utente che non ha i permessi per l'operazione che l'azione compie, l'azione fallisce in modo permanente (prima passava con privilegi admin cablati). Verificare i workflow esistenti creati da utenti non-admin.
- Nuove risposte d'errore: 403 su
/workflows/dry-run/candidatessenza permesso di lettura sul modulo; 422 sull'emissione fattura già in corso; 500INVOICE_LINK_FAILEDquando un documento è creato dal provider ma non collegabile localmente. listIssuedInvoicesnon espone più le emissioni in volo (claim non ancora finalizzato).- L'attribuzione delle azioni
assign_recordecreate_taskcon assegnatario passa dasystem.botall'autore del workflow (necessario perché la gerarchia si calcola sull'utente agente).update_fieldresta attribuito asystem.bot.
2026-07-12Versione 1.2.0
Aggiunto
- Diagnostica admin con metriche storiche
(
/admin/diagnostics). - Lo Studio visuale dei workflow raggiunge la parità col guidato.
2026-07-12Versione 1.1.0
Aggiunto
- Workflow builder completo: canvas visuale, condizioni raggruppate (AND/OR), nodo Wait (continuation), protezione anti-loop, dry-run + baseline, template email riusabili, stato draft/published, run-now in blocco, schedulazione cron, redacting per-campo, view-lock dei workflow visuali.
- Backup con upload S3, compressione zstd e retention remota.
- Admin utenti: password sicura, guardia auto-lockout, cambio password obbligatorio.
- Editor moduli custom: campo-titolo selezionabile, restore campo, conteggio record.
2026-06-23Versione 1.0.0
Prima release stabile. CRM self-hosted (Node/Express + PostgreSQL, frontend ES-module senza build runtime, Tailwind compilato localmente).
Funzionalità principali
- Dominio CRM completo: account, contatti, lead, trattative, attività, note, allegati.
- Moduli e campi custom: creazione a runtime di moduli/campi (incluse le picklist gestite), editor della struttura, record custom su JSONB.
- RBAC gerarchico con scope applicato in SQL e permessi a livello di campo; gestione utenti/ruoli dall'interfaccia di amministrazione.
- Audit log append-only + governance GDPR.
- Workflow con builder, scheduler e azioni (incluso l'invio email via SMTP).
- Dashboard a widget configurabile.
- Ricerca globale trasversale ai moduli (base + custom), nel rispetto di scope e permessi.
- Gestione duplicati / merge record con rilevamento automatico, pagina dedicata, storico e undo; fuzzy matching opzionale (pg_trgm) attivabile dall'admin.
- Reporting server-side con aggregazioni esatte + report builder ed export CSV/XLSX (senza dipendenze esterne).
- Import/export per modulo (CSV/XLSX) con ACL sui campi.
- Pannello manutenzione DB (diagnostica + ANALYZE/VACUUM) self-service per admin.
- Storage allegati pluggable: filesystem locale o bucket S3-compatibile (AWS/MinIO/Wasabi/Backblaze/R2), configurabile da UI con credenziali cifrate a riposo, test connessione e worker di migrazione tra backend (copia, verifica checksum, flip, eliminazione della sorgente) con progresso e log live.
Sicurezza
- Rimozione dell'admin di default + cambio password forzato; segreti JWT non-default obbligatori.
- Token di accesso revocabili; rate-limiting + account lockout; anti user-enumeration.
- MFA (TOTP) per admin; reset password self-service.
- Chiusura XSS stored + sanificazione nomi file; mass-assignment owner/assigned chiuso; ACL di scrittura sui campi in import; gate sui metadati di modulo.
- Guard SSRF nel runner dei webhook;
trust proxy+ IP client affidabile. - helmet + CSP:
script-srcstrict (nienteunsafe-inline, hash per il bootstrap tema), body limit, security headers. Tailwind compilato localmente (niente CDN a runtime per gli stili).
Note
- Pensato per deployment a singola istanza. Scala orizzontale (stato condiviso/Redis), observability avanzata e packaging/CI avanzato fanno parte della roadmap successiva.