From b7f5a663e26edcd24d6ec41452eaad78414a0ece Mon Sep 17 00:00:00 2001 From: cammo22 Date: Wed, 23 Sep 2026 14:26:36 +0200 Subject: [PATCH] Sistemazioni: seed mai in un eseguibile vero, documenti allineati, dipendenze MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le cose rimaste indietro nella 1.3.x. - Seed dimostrativo: in un eseguibile installato bastava DAPROD_DEMO=1 al primo avvio per ritrovarsi cammo/1234. AGENTS.md diceva "da togliere prima della Fase 10", ma l'installer esiste già. Ora lo accendono solo il flag di build della demo e l'app fuori pacchetto (npm run dev/demo). - Collegamento: il 2026-09-18 si è deciso niente account Tailscale e di valutare Tailcat, ma AGENTS.md (§1, §2, §3, §7, §12, §14), README e la barra di stato parlavano ancora di "Tailscale + fallback". Allineati; il pallino grigio ora si chiama "Collegamento" e dice che arriva in fase 8. - AGENTS.md: stato in testa fermo a "Prossima: Fase 5"; stack con scelte già fatte (Recharts, exceljs) ancora scritte come "o"; nota sulla cifratura ancora al condizionale. - Dipendenze: Electron 44.4.5 e vitest 5.0.1 (patch); uuid 11.1.1 forzato sotto exceljs, che usa solo v4, per chiudere l'avviso GHSA-w5hq-g745-h8pq senza scendere a exceljs 3 come proponeva npm audit fix. 0 vulnerabilità. - .claude/ (anteprime locali) fuori dalla repo. Provato: typecheck, 146 test, app compilata con Electron 44.4.5 che apre il database cifrato e applica tutte le migrazioni, barra di stato vista nell'anteprima. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 3 ++ AGENTS.md | 40 +++++++-------- README.md | 10 ++-- package-lock.json | 61 ++++++++++++----------- package.json | 9 +++- scripts/demo.mjs | 12 ++--- src/main/db/seed.ts | 12 +++-- src/main/server/index.ts | 2 +- src/renderer/src/components/StatusBar.tsx | 22 ++++++-- 9 files changed, 99 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index a41db3a..c5c07fe 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ Thumbs.db # --- Android: il progetto si genera nella CI (npx cap add android) --- /android/ + +# --- Configurazione locale di Claude Code (anteprime) --- +.claude/ diff --git a/AGENTS.md b/AGENTS.md index 986af96..5346916 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ > Documento master di progetto — generato da sessione di analisi e pianificazione DaProdProduzioni > Settore: software di controllo di gestione per consulenti finanziari aziendali (commercialisti, advisor, temporary manager) -> Stato: **in sviluppo — Fasi 0, 1, 2 e 4 completate, Fase 3 quasi** (impalcatura, auth, anagrafica, motore di calcolo, prime tre schermate). Prossima: Fase 5. Dettaglio in §13-bis. +> Stato: **in produzione — versione 1.4.0.** Fasi 0-7 fatte, 9 (import tollerante) fatta nel codice, 10 parziale, più Attività e Tempi, demo Android e Mac, portale dell'azienda, Personale, Area fiscale, Marginalità. Prossima: **Fase 8, collegamento studio ↔ aziende** (issue #43). Storia in §13-bis e seguenti, roadmap viva nell'issue #39. > Lingua progetto: codice EN, UI IT (convenzione DaProd, come IrideeCRM) --- @@ -42,7 +42,7 @@ Punti fermi dati dal cliente (testuali, dal brief): - **DaProdFinanza** (Consulente / *Master*) — l'app del professionista: gestisce tutti i clienti/aziende, tutta la suite Business, configurazione, import, simulazioni, vista aggregata multi-azienda. - **DaProdFinanza Cliente** (Azienda / *Satellite*) — app leggera installata presso ogni azienda cliente: serve a **caricare i dati** (fatture XML, estratti conto, inserimenti manuali) e a **tenere traccia** dei propri numeri (dashboard di sola lettura). Nessun accesso alla configurazione del piano dei conti né ai dati di altre aziende. - Interfaccia: un menu iniziale per **aggiungere/rimuovere Clienti e Aziende**, creazione rapida di una nuova azienda, poi dentro l'azienda la suite "Business" (screenshot analizzati, §10). -- Scambio dati **Consulente ↔ Azienda** sempre via **Tailscale** (da confermare "Tailscale" vs "Tailcat" — §14). +- Scambio dati **Consulente ↔ Azienda** su un canale privato cifrato, **senza account da creare**: si valuta **Tailcat** (deciso il 2026-09-18, dettaglio in §3 e §13 "Versione 1.1.0"). --- @@ -73,13 +73,13 @@ Stesso pattern validato in produzione su **IrideeCRM** — non ripartiamo da zer | Backend interno | **Node.js + Express** | Embedded nell'app Electron (REST sul Master) | | Database | **SQLite cifrato** — `better-sqlite3-multiple-ciphers` (SQLCipher) ✅ *deciso, §14.9* | dati finanziari (saldi banca, fidi, ricavi) più sensibili dei dati IRIS: DB cifrato a riposo fin dalla Fase 0, non solo DPAPI sui segreti | | Auth | **JWT** | Token con ruolo embedded | -| Networking | **Tailscale** (primario) + **fallback** (es. Cloudflare Tunnel) | Tailscale come rete privata di default (come IrideeCRM); se l'azienda cliente non riesce a configurarlo, un secondo trasporto di riserva — pattern già usato sul telefono di DaProdSuite ("si fa trovare dalla rete di casa, dal tunnel di Cloudflare o da Tailscale, e il client tiene quello che risponde") | -| Installer | **electron-builder** | Installer `.exe` offline, Tailscale bundled come in IRIS | -| Grafici | **Recharts** o **ECharts** | Per le viste a barre/linee/donut viste negli screenshot (12 grafici diversi tra le 7 schermate) | -| Import Excel | **exceljs** o **SheetJS (xlsx)** | Deve leggere il formato "Piano dei Conti" del cliente (§11.1) | -| Import XML | **fast-xml-parser** | Fatture elettroniche FatturaPA (§11.2) — schema da confermare appena arriva un file reale | +| Networking | **Tailcat** (da valutare in Fase 8) | Canale WireGuard cifrato senza account: il consulente mostra un indirizzo-codice, l'azienda lo inserisce. Sostituisce l'idea iniziale "Tailscale + fallback", scartata il 2026-09-18 perché chiedeva un account condiviso. Il trasporto sta dietro un'interfaccia, così si può cambiare | +| Installer | **electron-builder** | Installer NSIS, portable e demo per Windows; demo DMG per Mac e APK per Android costruiti da GitHub Actions. Il componente di collegamento si includerà con la Fase 8 | +| Grafici | **Recharts** ✅ | Tutti i grafici delle viste e del report PDF | +| Import Excel | **exceljs** ✅ | Legge il "Piano dei Conti" del cliente e le sue varianti (§11.1). SheetJS resta fuori: si installa solo dal suo sito (§14 punto 16) | +| Import XML | — | FatturaPA non è richiesta (§11.2): nessuna libreria finché non arriva un file vero | -**Differenza voluta rispetto a IRIS**: dati più sensibili (bilanci, fidi bancari, cassa) → vale la pena valutare cifratura del DB a riposo fin dalla Fase 2, non solo cifratura delle credenziali. +**Differenza voluta rispetto a IRIS**: dati più sensibili (bilanci, fidi bancari, cassa) → database **cifrato a riposo dalla Fase 0** (§12, §14 punto 9), non solo le credenziali. --- @@ -87,14 +87,14 @@ Stesso pattern validato in produzione su **IrideeCRM** — non ripartiamo da zer ``` [Azienda Cliente 1 - EXE] ──┐ -[Azienda Cliente 2 - EXE] ──┤── REST via Tailscale (o fallback) ──► [CONSULENTE - EXE + Express + SQLite centrale] +[Azienda Cliente 2 - EXE] ──┤── REST su canale cifrato (Tailcat) ──► [CONSULENTE - EXE + Express + SQLite centrale] [Azienda Cliente N - EXE] ──┘ PC/studio del consulente · archivio completo ``` - Ogni Azienda ha SQLite locale → può inserire dati e consultare i propri KPI **anche offline**. - Direzione prevalente del traffico: **Azienda → Consulente** (invio Excel/fatture, estratti conto, inserimenti manuali, chart of accounts aggiornato). Il Consulente elabora (riclassifica, configura le % dirette/indirette, lancia simulazioni) e i risultati elaborati sono visibili all'Azienda in sola lettura sul proprio Cliente. - **Aggiornamenti software**: come IRIS, il Master può distribuire l'installer aggiornato dell'app Cliente alle Aziende (stessa meccanica della cartella "aggiornamenti" scoperta in automatico) — risponde a "*app... per caricare aggiornamenti*" nel senso di "ricevere l'ultima versione", che coesiste con il senso di "caricare i propri dati" (assunzione, da confermare — §14). -- **Trasporto — deciso col cliente**: **Tailscale primario + fallback** (es. Cloudflare Tunnel, stesso pattern del telefono DaProdSuite). L'app Cliente prova Tailscale per primo (IP fisso, più sicuro, coerente con IRIS); se non raggiungibile (azienda che non ha/non sa configurare Tailscale) usa il trasporto di riserva. La status bar (§7) deve indicare **quale dei due è attivo**, non solo "connesso/offline". Tailscale resta comunque un prerequisito installato dall'installer, come in IrideeCRM; il fallback va progettato in Fase 8 insieme al resto del sync — non è detto serva fin dalla Fase 0. +- **Trasporto — deciso col cliente il 2026-09-18**: niente account Tailscale da far creare alle aziende. Si valuta **Tailcat** (dettaglio e limiti in §13 "Versione 1.1.0"): nessun account, un indirizzo-codice che lo studio mostra e l'azienda inserisce, canale WireGuard cifrato, porte TCP inoltrate. Passa dai relay gratuiti di Tailscale (si può mettere un relay proprio). La scelta iniziale "Tailscale primario + fallback" resta come ripiego se Tailcat non regge. La status bar (§7) deve dire **se il collegamento è attivo e da quando**, non solo "connesso/offline". Tutto si progetta in Fase 8 (issue #43). --- @@ -138,13 +138,13 @@ Stesso pattern validato in produzione su **IrideeCRM** — non ripartiamo da zer ## 7. Status bar (sempre visibile, in basso — pattern IRIS confermato dagli screenshot) -Negli screenshot analizzati è già presente in basso: `v1.5.0 · ● Database · ● Server · ● Tailscale · [prodotto] · [Backup] [↻ Aggiorna]`. Riprendiamo lo stesso pattern: +Negli screenshot analizzati è già presente in basso: `v1.5.0 · ● Database · ● Server · ● Tailscale · [prodotto] · [Backup] [↻ Aggiorna]`. Riprendiamo lo stesso pattern, con "Collegamento" al posto di "Tailscale" (§3): | Indicatore | Verde | Giallo | Rosso | |---|---|---|---| | Database locale | Connesso | — | Errore | -| Connessione Consulente (solo lato Azienda) | Online (specificare **via Tailscale** o **via fallback**) | Lenta | Offline | -| Tailscale | Attivo | Non attivo ma fallback in uso | Non attivo, nessun fallback disponibile | +| Connessione Consulente (solo lato Azienda) | Online | Lenta | Offline | +| Collegamento (Fase 8) | Canale attivo | In riconnessione | Non attivo | | Ultima sync | Timestamp | — | Mai sincronizzato | Pulsanti sempre presenti in basso a destra: **Backup** e **↻ Aggiorna** (refresh dati / pull aggiornamenti) — confermato identico in tutti e 7 gli screenshot. @@ -290,7 +290,7 @@ La nota *"se i numeri sono questi cosa devo fare per crescere?"* suggerisce un l - Password: **scrypt** (come IRIS). Sessione: **JWT** con segreto per-installazione. - Credenziali di sync cifrate con **DPAPI** (`safeStorage` Electron), mai in chiaro su disco — come IRIS. - **Novità rispetto a IRIS — decisa e implementata in Fase 0**: dati finanziari (saldi banca, fidi, utili) sono più sensibili di un CRM fotografico → **SQLite cifrato** con `better-sqlite3-multiple-ciphers` (SQLCipher) invece di `better-sqlite3` in chiaro. La chiave a 256 bit è generata al primo avvio e protetta da DPAPI; i backup ereditano la stessa cifratura. -- Comunicazione Consulente↔Azienda solo su rete privata Tailscale (mai esposto su internet pubblico). +- Comunicazione Consulente↔Azienda solo su canale privato cifrato (Tailcat, §3), mai un server esposto su internet pubblico. - File importati (XML/Excel) conservati come originali in `import/` per audit — mai solo il dato estratto. --- @@ -307,9 +307,9 @@ La nota *"se i numeri sono questi cosa devo fare per crescere?"* suggerisce un l | **5** | UI Capitale Circolante + Tesoreria/Cash Flow + Scadenziario (§10.5-10.6) | Previsione di cassa funzionante su dati reali | ✅ **Fatta** (sessione 2) | | **6** | UI Banche e Finanziamenti (§10.7) + collegamento rate→Cash Flow | Fidi/finanziamenti con impatto visibile in Tesoreria | ✅ **Fatta** (sessione 2) | | **7** | Analisi & Simulazioni (§10.8) | Scenario what-if salvabile e confrontabile | ✅ **Fatta** (sessione 2) | -| **8** | Sync Consulente↔Azienda via Tailscale (§6) + status bar (§7) | Due installazioni reali che si scambiano dati | ⬜ Prossima | +| **8** | Collegamento Consulente↔Azienda (§3, §6) + status bar (§7) | Due installazioni reali che si scambiano dati | ⬜ Prossima (issue #43) | | **9** | Import Excel avanzato: tolleranza a varianti di formato tra clienti/periodi (§11.1) | Import robusto su più file Excel reali diversi tra loro | ⬜ | -| **10** | Installer offline (electron-builder) per Consulente e Azienda | `.exe` funzionanti, Tailscale bundled | 🟡 **Parziale**: `.exe` installabile, portable e demo funzionanti. Mancano le due varianti separate e Tailscale bundled, che hanno senso solo dopo la Fase 8. **Regola del cliente (2026-09-16): una release a ogni aggiornamento importante, sempre con i tre eseguibili — installer, portable e demo** (`npm run dist` e `npm run dist:demo`). La prima così è la v0.0.5, con le Fasi 5 e 6 | +| **10** | Installer offline (electron-builder) per Consulente e Azienda | `.exe` funzionanti, collegamento incluso | 🟡 **Parziale**: `.exe` installabile, portable e demo funzionanti. Mancano le due varianti separate e il collegamento incluso, che hanno senso solo dopo la Fase 8. **Regola del cliente (2026-09-16): una release a ogni aggiornamento importante, sempre con i tre eseguibili — installer, portable e demo** (`npm run dist` e `npm run dist:demo`). La prima così è la v0.0.5, con le Fasi 5 e 6 | | **A** | Attività e Tempi (§10.11), idea presa da Ever Teams | Bacheca, timer, ore e valore per azienda | ✅ **Fatta** (versione 1.2.0) | | **B** | Demo per Android (§13, versione 1.2.0) | APK con i dati di esempio, dalla release | ✅ **Fatta** (versione 1.2.0) — da provare su più telefoni | | **11+** | Integrazioni Fase futura: connettore IRIS, Cassetto Fiscale, Open Banking, pianificazione fiscale, marginalità multi-dimensionale, assistente numeri | Una alla volta, dopo validazione col cliente | ⬜ | @@ -340,7 +340,7 @@ src/ - **Anagrafica Clienti/Aziende (§10.1)**: elenco clienti con le rispettive aziende, wizard "+ Nuovo cliente" e "+ Nuova azienda" (ragione sociale, P.IVA/CF, forma giuridica, tipo di attività, data inizio collaborazione), archiviazione e rimozione (soft delete di §6), ricerca, creazione delle credenziali per l'app Azienda. - Codici leggibili progressivi di §5: `CLI-0001`, `CLI-0001-AZ-01`. P.IVA univoca quando presente. - Cartelle di lavoro di §8 create automaticamente alla nascita di un'azienda (`import/`, `export/`, `backup/`). -- **Status bar di §7** con indicatori Database/Server/Tailscale e i pulsanti Backup e ↻ Aggiorna. Il backup produce un file cifrato in `Documenti/DaProdFinanza/backup/`. +- **Status bar di §7** con indicatori Database/Server/Collegamento e i pulsanti Backup e ↻ Aggiorna. Il backup produce un file cifrato in `Documenti/DaProdFinanza/backup/`. **Account dimostrativi (`src/main/db/seed.ts`)** @@ -351,7 +351,7 @@ src/ Insieme creano il cliente *Gruppo DaProd* e l'azienda *Pizzeria DaProd S.r.l.*, e le credenziali sono mostrate direttamente sulle card di scelta ruolo (con un pulsante che compila e accede). -⚠️ **Il seed non deve finire in un'installazione reale**: sono credenziali note, con password sotto la policy degli 8 caratteri. Gira solo con `npm run dev` oppure `npm run demo` (che imposta `DAPROD_DEMO=1`), e solo su un database ancora vuoto. Le password create dalla UI restano soggette alla policy. **Da rimuovere prima della Fase 10 (installer).** +⚠️ **Il seed non deve finire in un'installazione reale**: sono credenziali note, con password sotto la policy degli 8 caratteri. Gira solo fuori pacchetto (`npm run dev`, `npm run demo`) e nella versione demo (flag di build `__DEMO_BUILD__`), e solo su un database ancora vuoto. Dalla 1.4.0 nessuna variabile d'ambiente lo accende in un eseguibile vero: prima `DAPROD_DEMO=1` al primo avvio bastava. Le password create dalla UI restano soggette alla policy. **Eseguibili (anticipo parziale della Fase 10)** @@ -373,7 +373,7 @@ Il binding nativo del database cifrato sta fuori dall'archivio `asar` (`asarUnpa **Cosa è volutamente un segnaposto** - Le sette viste Business (§10.2-§10.8) mostrano solo l'elenco dei moduli con la fase in cui arriveranno: senza motore di riclassificazione, riempirle di dati finti su un gestionale contabile sarebbe fuorviante. -- L'indicatore Tailscale resta grigio: il trasporto Consulente↔Azienda è Fase 8. Il server Express ascolta oggi **solo su 127.0.0.1** con porta effimera. +- L'indicatore del collegamento resta grigio: il trasporto Consulente↔Azienda è Fase 8. Il server Express ascolta oggi **solo su 127.0.0.1** con porta effimera. **Fase 2 — schema del motore finanziario** (migrazione `002_financial_model`) @@ -789,7 +789,7 @@ Controlli: 146 test (i motori nuovi su conti fatti a mano), `verify:schema` 86/8 **Risolti (sessione di analisi iniziale):** 1. ~~File XML di esempio mancante~~ → **chiarito**: era un refuso, il cliente intendeva l'Excel (§11.1). Nessun file XML esiste o è richiesto ora; FatturaPA resta solo un'idea di fase futura (§11.2). -2. ~~"Tailscale" o "Tailcat"?~~ → **deciso**: Tailscale primario + trasporto di fallback (tipo Cloudflare Tunnel). Dettaglio in §2/§3/§7. +2. ~~"Tailscale" o "Tailcat"?~~ → **deciso due volte**: prima Tailscale primario + fallback; poi, il 2026-09-18, niente account Tailscale e si valuta **Tailcat** (§3, §13 "Versione 1.1.0"). Si conferma o si cambia in Fase 8. 3. ~~Licenza e visibilità della repo pubblica~~ → **deciso**: repo pubblica, licenza **MIT**, metodologia inclusa senza restrizioni in `docs/MODELLO_FINANZIARIO.md`. Resta comunque valida la regola di §0: i **file originali** (screenshot con branding IRIS, Excel col nome del cliente reale "Indy") non vanno mai committati — è una questione di riservatezza del singolo cliente del consulente, non di apertura della metodologia in sé. **Risolti (sessione 1 — Fasi 0/1):** diff --git a/README.md b/README.md index 780cdef..e5c2231 100644 --- a/README.md +++ b/README.md @@ -127,9 +127,11 @@ che i numeri di un'azienda escano dal computer di chi ha il diritto di vederli. | Cosa fa | Configura, riclassifica, simula scenari | Carica i propri dati, consulta i propri KPI | | Se salta la rete | Continua a funzionare | Continua a funzionare | -I due programmi si parlano su una rete privata (Tailscale, con un collegamento di -riserva per quando un'azienda non riesce a configurarlo). Nessun server pubblico, -nessun dominio da comprare, nessun dato che passa da terzi per l'uso quotidiano. +I due programmi si parleranno (è il prossimo passo, la fase 8) su un canale privato +e cifrato, senza account da creare: lo studio mostra un codice, l'azienda lo +inserisce. Nessun server pubblico, nessun dominio da comprare, e chi sta in mezzo +vede solo dati cifrati. Oggi il programma Azienda funziona sullo stesso computer +dello studio, con il suo accesso. ## Novità della 1.3.1 @@ -467,7 +469,7 @@ nell'IndexedDB; Express è un piccolo router compatibile (`src/web/shims/express e le chiamate `fetch` all'indirizzo del backend restano nella pagina (`src/web/bridge.ts`). Capacitor la impacchetta in un APK sulla CI di GitHub (`.github/workflows/android-demo.yml`), a ogni release. Dettagli in -[`AGENTS.md`](./AGENTS.md), versione 1.2.0. +[`AGENTS.md`](./AGENTS.md). ### L'interfaccia (1.3.0) diff --git a/package-lock.json b/package-lock.json index aa5b52a..2cdf53a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "@types/sql.js": "^1.4.11", "@vitejs/plugin-react": "^5.1.0", "docx-preview": "^0.4.1", - "electron": "^44.3.0", + "electron": "^44.4.5", "electron-builder": "^26.0.12", "electron-vite": "^5.0.0", "jszip": "^3.10.2", @@ -48,7 +48,7 @@ "tailwindcss": "^4.3.3", "typescript": "^5.9.3", "vite": "^7.1.0", - "vitest": "^5.0.0" + "vitest": "^5.0.1" } }, "node_modules/@babel/code-frame": { @@ -3152,14 +3152,14 @@ } }, "node_modules/@vitest/mocker": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz", - "integrity": "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.1.tgz", + "integrity": "sha512-6K1DoBNAPGvuOcSsGA4D6x+5zEEff/KmOOP3uetT2TrGpVfI+HRHRnJJfKi5ib/g1vx8IYHQD8s0pbJz8WQI7Q==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.31", - "@vitest/spy": "5.0.0", + "@vitest/spy": "5.0.1", "estree-walker": "^3.0.3", "magic-string": "^1.2.3" }, @@ -3180,9 +3180,9 @@ } }, "node_modules/@vitest/mocker/node_modules/magic-string": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.3.1.tgz", - "integrity": "sha512-rm91zr2Ou+XueDTohjQQjdQEcYM6zVi8KVUCG8Ec3vHwUEKrhSdCNyfuIywkA6hcCAteIn0ZOtAHA6eGpiX+Pg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz", + "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==", "dev": true, "license": "MIT", "dependencies": { @@ -3190,9 +3190,9 @@ } }, "node_modules/@vitest/spy": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.0.tgz", - "integrity": "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.1.tgz", + "integrity": "sha512-rbto/mF/SGERxEgYOek7Xm6B9b+y+mVoo+f4b2LymYO8zM1b7uB5nHuhVMTP2hxdzgxvGiZYGxGIaMvL5y180Q==", "dev": true, "license": "MIT", "funding": { @@ -4815,9 +4815,9 @@ } }, "node_modules/electron": { - "version": "44.3.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-44.3.0.tgz", - "integrity": "sha512-St9EV7F2VtYaYWD2qaAjBwUgKxx39eJOUsUJ5+/1113sqbVfNqv4Dbm/W1rN7qmYSPa+mWwR6yr+b7MfgjgVfQ==", + "version": "44.4.5", + "resolved": "https://registry.npmjs.org/electron/-/electron-44.4.5.tgz", + "integrity": "sha512-SjgoaeYsSWZfJzubgQU7juvuXMTvn6/e1gAHdGFA/yuMbpF+I+skYqIJ6DdXBXHeWbkbpNpmwZCTpiivtlWZSw==", "license": "MIT", "dependencies": { "@electron-internal/extract-zip": "^1.0.1", @@ -9250,13 +9250,16 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/vary": { @@ -9850,14 +9853,14 @@ } }, "node_modules/vitest": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.0.tgz", - "integrity": "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.1.tgz", + "integrity": "sha512-iA95lQbKEkvrtTkdAgnWbXfbipWiiWe/hDl2P5tMi6WFwD76G0NxXAGp/M9EOcYupeGJRr6wppMc7CoA41TQjg==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/mocker": "5.0.0", + "@vitest/mocker": "5.0.1", "chai": "^6.2.2", "es-module-lexer": "^2.3.2", "expect-type": "^1.4.0", @@ -9883,12 +9886,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "5.0.0", - "@vitest/browser-preview": "5.0.0", + "@vitest/browser-playwright": "5.0.1", + "@vitest/browser-preview": "5.0.1", "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0", - "@vitest/coverage-istanbul": "5.0.0", - "@vitest/coverage-v8": "5.0.0", - "@vitest/ui": "5.0.0", + "@vitest/coverage-istanbul": "5.0.1", + "@vitest/coverage-v8": "5.0.1", + "@vitest/ui": "5.0.1", "happy-dom": "*", "jsdom": "*", "vite": "^6.4.0 || ^7.0.0 || ^8.0.0" diff --git a/package.json b/package.json index e9f50e3..0648d04 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@types/sql.js": "^1.4.11", "@vitejs/plugin-react": "^5.1.0", "docx-preview": "^0.4.1", - "electron": "^44.3.0", + "electron": "^44.4.5", "electron-builder": "^26.0.12", "electron-vite": "^5.0.0", "jszip": "^3.10.2", @@ -66,6 +66,11 @@ "tailwindcss": "^4.3.3", "typescript": "^5.9.3", "vite": "^7.1.0", - "vitest": "^5.0.0" + "vitest": "^5.0.1" + }, + "overrides": { + "exceljs": { + "uuid": "^11.1.1" + } } } diff --git a/scripts/demo.mjs b/scripts/demo.mjs index 0e82da8..491ea2b 100644 --- a/scripts/demo.mjs +++ b/scripts/demo.mjs @@ -1,14 +1,14 @@ /** - * Avvia la build di produzione con il seed dimostrativo attivo - * (account `cammo` e `Pizzeria DaProd`, password `1234`). + * Avvia la build compilata (`out/`) fuori pacchetto, quindi con il seed + * dimostrativo attivo (account `cammo` e `Pizzeria DaProd`, password `1234`). * - * In `npm run dev` il seed è già attivo di suo: questo script serve solo per - * provare l'app compilata senza passare dal wizard di primo avvio. + * Serve a provare l'app compilata senza passare dal wizard di primo avvio. + * Il seed si accende perché l'app non è impacchettata, non per una variabile + * d'ambiente: un eseguibile vero non lo accende mai (vedi db/seed.ts). */ import { spawn } from 'node:child_process' import electron from 'electron' spawn(electron, ['.'], { - stdio: 'inherit', - env: { ...process.env, DAPROD_DEMO: '1' } + stdio: 'inherit' }).on('exit', (code) => process.exit(code ?? 0)) diff --git a/src/main/db/seed.ts b/src/main/db/seed.ts index 8697990..379349b 100644 --- a/src/main/db/seed.ts +++ b/src/main/db/seed.ts @@ -18,10 +18,12 @@ import { saveAppSettings } from '../server/services/settings.service' * provare i ruoli di AGENTS.md §4 senza passare dal wizard di primo avvio. * * ⚠️ Non deve MAI finire in un'installazione reale: sono credenziali note e con - * password fuori policy. Gira solo in sviluppo (`npm run dev`) oppure con - * `DAPROD_DEMO=1` impostata a mano, nella versione demo costruita da - * `npm run dist:demo`, e solo su un database ancora vuoto. La versione demo usa - * una cartella dati tutta sua (vedi build-flags.ts). + * password fuori policy. Gira solo fuori pacchetto (`npm run dev`, `npm run + * demo`) e nella versione demo costruita da `npm run dist:demo`, e solo su un + * database ancora vuoto. La versione demo usa una cartella dati tutta sua (vedi + * build-flags.ts). In un eseguibile vero nessuna variabile d'ambiente lo + * accende: prima bastava `DAPROD_DEMO=1` al primo avvio per ritrovarsi + * `cammo / 1234` in un'installazione reale. */ export const DEMO_PASSWORD = '1234' @@ -37,7 +39,7 @@ export const DEMO_ACCOUNTS: DemoAccount[] = [ ] export function isDemoMode(): boolean { - return DEMO_BUILD || is.dev || process.env['DAPROD_DEMO'] === '1' + return DEMO_BUILD || is.dev } /** true quando il seed è attivo e i dati sono effettivamente presenti. */ diff --git a/src/main/server/index.ts b/src/main/server/index.ts index 10db15a..487d283 100644 --- a/src/main/server/index.ts +++ b/src/main/server/index.ts @@ -18,7 +18,7 @@ import { settingsRouter } from './routes/settings.routes' * Backend REST embedded nel processo main — AGENTS.md §2/§3. * * In Fase 1 ascolta solo su 127.0.0.1 con porta effimera: è la UI locale a - * consumarlo. L'esposizione verso le app Azienda via Tailscale è Fase 8 (§13) — + * consumarlo. L'esposizione verso le app Azienda (canale cifrato, §3) è Fase 8 — * qui non si apre nulla verso la rete. */ const HOST = '127.0.0.1' diff --git a/src/renderer/src/components/StatusBar.tsx b/src/renderer/src/components/StatusBar.tsx index 56e1e26..f4c5332 100644 --- a/src/renderer/src/components/StatusBar.tsx +++ b/src/renderer/src/components/StatusBar.tsx @@ -7,7 +7,7 @@ import { applicaZoom, useZoom, ZOOM_MAX, ZOOM_MIN, ZOOM_PASSO } from '../lib/zoo /** * Status bar sempre visibile in basso — AGENTS.md §7. - * Tailscale e "ultima sync" restano grigi finché non arriva la Fase 8. + * Collegamento e "ultima sync" restano grigi finché non arriva la Fase 8. */ type Tone = 'ok' | 'warn' | 'off' @@ -17,9 +17,17 @@ const DOT: Record = { off: 'bg-ink-600' } -function Indicator({ tone, label }: { tone: Tone; label: string }): React.JSX.Element { +function Indicator({ + tone, + label, + title +}: { + tone: Tone + label: string + title?: string +}): React.JSX.Element { return ( - + {label} @@ -72,8 +80,12 @@ export function StatusBar({ version }: { version: string }): React.JSX.Element { - {/* Fase 8: qui comparirà "via Tailscale" o "via fallback" (§7). */} - + {/* Fase 8: qui comparirà lo stato del canale con le aziende (§3, §7). */} + Ultima sync: {health?.last_sync ?? 'mai sincronizzato'}