Files
richiesta-software/architettura.md
T

274 lines
21 KiB
Markdown
Raw Normal View History

# Architettura del software
**Progetto:** Gestionale per enti del Terzo Settore
**Documento:** `architettura.md`
2026-09-27 19:41:16 +02:00
**Versione:** 0.4.5 · **Data:** 27/09/2026 · **Stato:** Bozza, proposta da confermare; uso interno
**Allineato a:** `richiesta.md` v0.4 · **Schema di versione:** vedi `indice-documenti.md`
**Cosa contiene:** come si costruisce il software: forma dell'applicazione, componenti, dati, permessi, stack, sicurezza, infrastruttura e rilascio. I requisiti non si ripetono: si citano con il codice. Servizi e prezzi di riferimento sono in `costi-ricorrenti.md`, le scelte ancora aperte (B) in `domande-cliente.md` §3, l'ordine di realizzazione in `blueprint.md`.
Le proposte 🔸 di questo documento diventano decisioni (Dn in `richiesta.md` §7) quando Davide le approva.
---
## 1. Vincoli di partenza
Ogni scelta dei paragrafi successivi nasce da uno di questi vincoli.
| Vincolo | Da dove | Conseguenza per l'architettura |
|---|---|---|
| Un solo sviluppatore (Davide, con Claude) | Contesto di progetto | Poche parti in movimento: un'applicazione, un database, strumenti maturi e documentati |
| Budget vincolato e rendicontabile (bando) | Contesto di progetto | Solo software open source senza licenze; servizi a pagamento solo dove li impone la legge o un requisito (firma, marca, conservazione) |
| Circa 100 utenti, uso da gestionale d'ufficio | RT-11 (⏳ Q1) | Un server per ambiente basta; nessuna scalabilità orizzontale |
| Applicazione web da computer | RT-12 | Un'unica interfaccia web; nessuna app, nessun adattamento a smartphone |
| Ogni ente vede solo i propri dati | RT-1, RT-2, D2 | Separazione per ente nell'applicazione **e** nel database (§4) |
| PostgreSQL e migrazioni | ✅ D12, RT-16 | Struttura dei dati modificata solo con migrazioni versionate (§4, §8) |
| Hosting nell'UE | RT-13 | Server e servizi esterni con dati nell'UE |
| Servizi trasferibili al cliente a fine primo anno | RT-15, D10, D11 | Configurazione descritta nel repository, fornitori che trasferiscono account, nessun servizio difficile da spostare |
| Valore probatorio dei libri sociali | RF-4.5–4.7, RT-9 | Documenti archiviati non modificabili; registro delle operazioni |
| Dati personali di molte persone, antiriciclaggio, possibili dati art. 9 | `richiesta.md` §5, RT-10 | Privacy by design (§7) |
---
## 2. Forma dell'applicazione 🔸 (B2.6)
### 2.1 Proposta
**Un'unica applicazione web** (monolite modulare) con **pagine generate dal server** e interattività leggera nel browser, **un solo database** PostgreSQL e un **processo in background** per i lavori lenti o pianificati.
- I moduli M1–M9 sono parti separate dello stesso codice e comunicano con chiamate interne, non attraverso la rete.
- Il processo in background invia le email, chiede firme e marche temporali, genera i PDF e importa i file; il pianificatore lancia alert e solleciti (§3).
### 2.2 Perché
- **RT-11:** con circa 100 utenti un'applicazione su un server regge il carico; nessuna parte deve crescere separatamente dalle altre.
- **Un solo sviluppatore:** un linguaggio, un rilascio, un registro degli errori.
- **Natura dei moduli:** schede, tabelle, procedure guidate (RF-6.1, RF-7.1) e flussi di approvazione (RT-3). Non c'è interattività da applicazione (modifica contemporanea, uso offline) che giustifichi un'applicazione browser separata.
- **RT-15:** un'applicazione sola si documenta e si consegna più facilmente.
**Eccezione da tenere d'occhio:** se Q19 ha risposta **(c)** (ente e studio lavorano insieme sullo stesso documento), le pagine di M6 e M7 richiedono la modifica contemporanea in tempo reale. La forma dell'applicazione resta la stessa, ma serve un componente in più, da stimare a parte (B1.2).
### 2.3 Alternative scartate
| Alternativa | Perché no |
|---|---|
| Microservizi (un servizio per modulo) | Nessun requisito di scalabilità separata; moltiplica rilasci, monitoraggio e punti di guasto per un solo sviluppatore |
| Applicazione browser separata (SPA) + API | Due applicazioni da sviluppare, versionare e consegnare; nessuna app mobile (RT-12) né API per terzi richieste |
| Funzioni serverless | Firma, importazione e PDF sono lavori con stato e tentativi ripetuti, più semplici con un processo sempre attivo; legano a un fornitore (RT-15) |
| Un database per ente | La separazione (RT-1) si ottiene nello stesso database con la row-level security (D12); più database moltiplicano migrazioni (RT-16) e backup |
**Non si prepara nulla "per il futuro"** (es. più studi sulla stessa piattaforma): D2 prevede un solo studio. Se cambiasse, sarebbe una nuova versione dei requisiti.
---
## 3. Componenti comuni
Servono a più moduli e si costruiscono una volta sola (pacchetti P2 e P3 di `blueprint.md`).
| Componente | Cosa fa | Requisiti | Scelta |
|---|---|---|---|
| Accesso | Login, seconda verifica con codice da app (TOTP), recupero password via email. Il referente dell'ente riceve un **link di attivazione a scadenza**, mai una password per email (W1 passo 6) | RT-2, RT-10 | 🔸 Seconda verifica obbligatoria per lo studio (vede tutti gli enti), consigliata per gli enti |
| Ruoli e permessi | Chi può fare quale azione su quale ente (§5) | RT-1, RT-2 | 🔸 |
| Flusso di approvazione | Un solo componente a stati per M4, M5 (chiusura annuale), M6 e M7: ammette solo i passaggi di stato previsti e li registra tutti | RT-3; W4, W5, W6, W8 | 🔸 B2.4 |
| Procedura guidata a sezioni | Compilazione per sezioni, salvataggio di ogni sezione, ripresa del lavoro | RF-5.7, RF-6.1, RF-7.1 | 🔸 |
| Notifiche | Un solo servizio: scrive la notifica nell'app, mette in coda l'email, registra la lettura. Email senza dati personali, solo un link all'applicazione (§7) | RT-4, RF-8.2 | 🔸 B2.3 |
| Pianificatore | Alert sulle scadenze di pagamento, alert per il caricamento dei documenti, solleciti | RF-1.9, RF-5.1; W2, W5 | 🔸 |
| Lavori in background | Esegue i lavori lenti. Se un fornitore non risponde, riprova con attese crescenti e lascia il documento in uno **stato esplicito** (es. "in attesa di firma"), mai a metà | RT-5–RT-8 | 🔸 |
| Firma elettronica | Componente sostituibile: firma simulata in sviluppo, sandbox del fornitore negli ultimi 40 giorni, fornitore reale in produzione (`costi-ricorrenti.md` §3, nota 3) | RT-5 (⏳ Q4) | ✅ Firma simulata in sviluppo; fornitore: B1.4 |
| Marca temporale e conservazione | Marca via API sull'impronta del documento. La conservazione digitale è richiesta da [D]: a norma presso un conservatore se Q9 lo richiede, altrimenti archivio interno con marca temporale | RT-6 (⏳ Q9) | B1.4; ⚖️ C4, C6 |
| Generazione documenti | PDF da modelli HTML per ciò che si stampa (offerte, proforma, libri, verbali, Modello D); Word modificabile per progetti e relazioni, a partire dai modelli del cliente | RT-7, RF-5.7, RF-6.3 (⏳ Q13) | 🔸 Librerie open source dello stack (§6) |
| Importazione | Excel (🔸 anche CSV, formato non citato nelle fonti) con **mappatura delle colonne salvata per ente e banca**, riusata nei trimestri successivi; controllo riga per riga con l'elenco degli errori, nessuna riga scartata in silenzio; il PDF resta un allegato | RT-8, RF-5.2–5.3 (⏳ Q10) | 🔸 B1.3 |
| Registro delle operazioni | Chi, cosa, quando, valore prima e dopo, per i dati con valore probatorio e per i dati personali; l'applicazione non lo può modificare | RT-9 | 🔸 B2.5; anche la consultazione dei dati antiriciclaggio (⚖️ C3) |
| Archivio file | Documenti caricati e generati, fuori dalla cartella dell'applicazione e compresi nei backup; antivirus sui file caricati dagli enti | RT-8, RT-10, RT-15 | 🔸 |
| Tabelle di configurazione | Valori che lo studio cambia senza sviluppo: catalogo servizi, voci del Modello D, calendario delle scadenze con eccezioni per ente, tariffe orarie del volontariato | RF-1.1, RF-5.1, RF-5.5, RF-9.3 | 🔸 B2.2 |
---
## 4. Dati
| Tema | Scelta | Perché |
|---|---|---|
| Database | ✅ PostgreSQL, struttura modificata solo con migrazioni | D12, RT-16 |
| Separazione per ente | ✅ Colonna dell'ente su ogni tabella con dati di un ente, più **row-level security**: il database rifiuta le righe di altri enti anche se l'applicazione sbaglia un filtro. 🔸 L'applicazione imposta l'ente dell'utente all'inizio di ogni transazione e si collega con un utente del database che non è proprietario delle tabelle e non può ignorare la row-level security (altrimenti la protezione non si applica) | RT-1, D12, B2.1 |
| Persone | 🔸 Una scheda per persona con più ruoli; libro soci e registro volontari fanno riferimento alla scheda | RF-3.3, W3 |
| Documenti archiviati | 🔸 Nessuna modifica né cancellazione dopo l'archiviazione, bloccata anche nel database (un trigger rifiuta le modifiche alle righe archiviate); correzioni e cessazioni sono nuove voci collegate | W4 passi 5 e 7, RT-9 |
| Nuove categorie o campi | Con una migrazione | RF-3.2, D12 |
| Cancellazione di dati personali | Gli utenti si disattivano, non si cancellano: il registro deve poter dire chi ha fatto cosa. Tempi di conservazione degli altri dati personali: ⚖️ C1, C3 | RT-9, RT-10 |
| Dati in test | Solo dati finti, mai copie della produzione | RT-10 |
---
## 5. Ruoli e permessi
- **Due tipi di utente** (D1): **studio** (interno), che vede tutti gli enti, ed **ente** (esterno), legato 🔸 a un solo ente (RT-1).
- **Permessi per azione, non solo per modulo:** vedere, creare, modificare, inviare in revisione, approvare. Chi fa cosa deriva dalla colonna "Operatore" di [X] e dalle colonne "Chi inserisce" e "Chi controlla" di `richiesta.md` §2; il dettaglio passo per passo è nella colonna "Chi" di `workflow.md`.
- 🔸 Tra gli utenti dello studio, un ruolo di **amministratore** crea e disattiva gli utenti (W1 passo 6).
```mermaid
flowchart TD
U[Richiesta di un utente autenticato] --> T{Tipo di utente}
T -->|studio| S[Tutti gli enti]
T -->|ente| E[Solo il proprio ente<br/>filtro dell'applicazione + row-level security]
S --> P{Azione permessa<br/>a questo utente?}
E --> P
P -->|sì| OK[Eseguita e registrata<br/>RT-9]
P -->|no| KO[Rifiutata]
```
---
## 6. Stack applicativo ⏳ B1.10
Linguaggio e framework non sono ancora scelti. Qui ci sono i criteri, ricavati dai requisiti, e il confronto.
### 6.1 Criteri
| Criterio | Da dove |
|---|---|
| Framework "completo": accesso, permessi, migrazioni, coda, pianificatore, email e validazione dei moduli già inclusi | RT-2, RT-4, RT-16, RF-1.9, RF-5.1; un solo sviluppatore |
| Supporto maturo a PostgreSQL e alla row-level security | D12, RT-1 |
| Librerie open source per PDF, Word ed Excel | RT-7, RT-8; budget |
| Diffusione: chi subentra (il cliente, un altro sviluppatore) deve trovare competenze | RT-15; rischio di dipendenza da una sola persona |
| Conoscenza di Davide | Controllare con competenza il codice scritto con Claude |
### 6.2 Confronto
| | Laravel (PHP) | Django (Python) |
|---|---|---|
| Accesso, permessi, migrazioni | Inclusi | Inclusi (i permessi sul singolo record richiedono una libreria) |
| Coda e pianificatore | Inclusi; la coda può usare PostgreSQL | Con librerie aggiuntive (alcune usano PostgreSQL, altre Redis) |
| Notifiche nell'app con stato di lettura (RF-8.2) | Incluse (notifiche salvate nel database) | Da sviluppare o con una libreria |
| Pannello per le tabelle di configurazione (§3) | Con una libreria open source (es. Filament) | Incluso (admin di Django) |
| PDF / Word / Excel | dompdf o Chrome headless / PHPWord / PhpSpreadsheet | WeasyPrint / python-docx o docxtpl / openpyxl |
| Pagine dal server con interattività leggera | Blade + Livewire | Template + htmx |
| Row-level security | Ente impostato a ogni transazione | Stesso meccanismo |
Rails, .NET e Node.js possono coprire gli stessi requisiti; il confronto si limita alle due opzioni più aderenti ai criteri del §6.1 e si estende se Davide conosce uno di questi stack.
2026-09-27 19:41:16 +02:00
**Orientamento 🔸 (B1.10):** sui requisiti Laravel e Django si equivalgono; decide la **conoscenza di Davide**, perché nel controllo del codice conta più di qualunque differenza tecnica. Davide conosce Python, non PHP: **Django è l'orientamento attuale**, non ancora deciso (D). I pezzi che Django non include di serie restano piccoli da colmare: coda e pianificatore con Django-Q2 (su PostgreSQL, senza Redis, coerente con il punto sotto) e notifiche con stato di lettura con un modello dedicato o django-notifications-hq; i permessi a livello di singolo record restano comunque affidati alla row-level security di PostgreSQL (D12), non al framework.
**In entrambi i casi:**
- 🔸 **niente Redis:** con circa 100 utenti coda e cache sul database bastano, e c'è un servizio in meno da gestire, salvare e trasferire (RT-15). Si aggiunge solo se le misure in produzione lo richiedono;
- nessun adattamento a smartphone (RT-12).
---
## 7. Sicurezza e privacy by design
Per ogni misura: cosa protegge e da quale requisito nasce. ⚖️ Le misure finali dipendono dalle verifiche C1, C2, C3 e C13 (valutazione d'impatto, da chiudere prima dello sviluppo).
| Misura | Cosa protegge | Rif. |
|---|---|---|
| HTTPS su tutto | Dati in transito | RT-10 |
| Seconda verifica all'accesso (§3) | Account dello studio, che vede tutti gli enti | RT-1, RT-10 |
| Row-level security (§4) | Dati di un ente dagli utenti di un altro, anche con un errore nel codice | RT-1 |
| Limite ai tentativi di accesso, sessioni a scadenza | Accessi non autorizzati | RT-10 |
| Backup cifrati, con una copia fuori dal server (`costi-ricorrenti.md` §3, nota 5) | Perdita o furto dei dati | RT-10, RT-15 |
| 🔸 Documenti d'identità antiriciclaggio cifrati nell'archivio | Dati antiriciclaggio | ⚖️ C3 |
| Email, notifiche e log senza dati personali, solo link | Dati che escono dal sistema | RT-4, RT-10 |
| Monitoraggio degli errori in regione UE, con i dati personali filtrati prima dell'invio (`costi-ricorrenti.md` §3, nota 6) | Dati personali contenuti negli errori | RT-10, RT-13 |
| Antivirus sui file caricati | Server e utenti dello studio | RT-8 |
| Test con dati finti ed email intercettate | Persone reali durante i test | RT-10 |
| Registro delle operazioni (§3) | Valore probatorio, controllo degli accessi | RT-9 |
| 🔸 Misure aggiuntive per i possibili dati art. 9 | Categorie particolari di dati | ⚖️ C2 |
| Aggiornamenti di sicurezza di sistema e librerie | Vulnerabilità note | RT-10; dal secondo anno rientra nel contratto di manutenzione separato (D11), termini e ore non ancora decisi |
---
## 8. Infrastruttura e rilascio
### 8.1 Ambienti
Sviluppo, test e produzione come in `costi-ricorrenti.md` §1, dove sono anche servizi e dimensioni di riferimento.
🔸 **B2.7: un server per ambiente**, con applicazione, database e processo in background in **container** descritti nel repository (Docker Compose).
- **RT-16:** test e produzione hanno la stessa configurazione, quindi le migrazioni si applicano identiche.
- **RT-15:** chi riceve i servizi ricrea l'ambiente dalla configurazione del repository, senza istruzioni a memoria.
- **Perché non servizi cloud gestiti** (database gestito, container gestiti): con 100 utenti non servono, costano di più con importi meno prevedibili (budget del bando) e legano al fornitore.
- **Perché non Kubernetes:** serve a coordinare molti server; qui ce n'è uno per ambiente.
### 8.2 Ciclo di rilascio
```mermaid
flowchart LR
A[Sviluppo] --> B[Invio al repository]
B --> C[Test automatici]
C -->|falliti| A
C -->|superati| D[Rilascio in test<br/>con le migrazioni]
D --> E[Collaudo]
E -->|problemi| A
E -->|ok| F[Backup della produzione]
F --> G[Rilascio in produzione<br/>con le stesse migrazioni]
G --> H[Verifica dopo il rilascio]
H -->|errore| I[Ripristino della versione<br/>precedente e del backup]
H -->|ok| J[Rilascio concluso]
```
- Repository e rilascio automatico sul server Git di Davide (`costi-ricorrenti.md` §3, nota 2).
- Nessuna correzione a mano in produzione: un errore si corregge con un nuovo rilascio o con il ripristino (RT-16).
- 🔸 **Prova di ripristino** del backup su un ambiente separato, almeno una volta a trimestre: un backup mai provato non dà garanzie.
- Monitoraggio di errori e disponibilità: `costi-ricorrenti.md` §3.
- Le procedure operative (rilascio, ripristino, fornitore che non risponde) si scrivono quando lo stack è scelto: fanno parte del documento di consegna richiesto da RT-15 (P16 in `blueprint.md`).
---
## 9. Moduli e componenti
| Modulo | Componenti del §3 | Servizi esterni |
|---|---|---|
| M1 Gestione cliente | Generazione documenti, firma, pianificatore, notifiche, configurazione (catalogo) | Firma, email |
| M2 Anagrafica enti | Registro delle operazioni | — |
| M3 Anagrafica stakeholder | Registro delle operazioni | — |
| M4 Libri sociali | Flusso di approvazione, firma (⏳ Q4), marca, conservazione (⏳ Q9), generazione documenti | Firma, marca, conservazione |
| M5 Contabilità | Importazione, pianificatore, configurazione (Modello D, calendario), procedura guidata, flusso di approvazione, generazione documenti | Email |
| M6 Progettazione | Procedura guidata, flusso di approvazione (⏳ Q19), generazione Word (⏳ Q13) | — |
| M7 Rendicontazione sociale | Procedura guidata che legge i dati di M2, M3 e M5 (RF-7.2), flusso di approvazione, generazione documenti | — |
| M8 Circolari | Notifiche con stato di lettura | Email |
| M9 Valutazione volontariato | Configurazione (tariffe, ⏳ Q15) | — |
---
## 10. Fuori perimetro
Per evitare aggiunte non richieste durante lo sviluppo:
- app per smartphone e adattamento a schermi piccoli (RT-12);
- motore di flussi configurabile dall'utente: un solo flusso a stati nel codice (RT-3);
- firma, marca e conservazione costruite in proprio: servono fornitori qualificati (B1.4, ⚖️ C4);
- lettura automatica dei PDF finché Q10 non la chiede (B1.3);
- fattura elettronica sviluppata da zero (B1.5, ⏳ Q5);
- importazione di dati esistenti all'avvio (RT-14);
- più lingue, più studi sulla stessa piattaforma (D2), API per terzi: nessun requisito.
---
## 11. Cosa può cambiare l'architettura
| Punto aperto | Effetto |
|---|---|
| Q1 numero di enti | Dimensione del server di produzione e spazio disco (`costi-ricorrenti.md` §4) |
| Q4 tipo di firma | Implementazione del componente di firma |
| Q9, ⚖️ C6 conservazione | Conservatore con o senza API; un archivio o uno per ente; eventuale passo manuale in W4 |
| Q10 estratti conto PDF | Componente di lettura dei PDF |
| Q5 fattura elettronica | Integrazione con un servizio esterno |
| Q13 schema dei progetti | Struttura dei dati di M6 e formato di esportazione |
| Q19 risposta (c) | Modifica contemporanea in tempo reale per M6 e M7 (§2.2) |
| ⚖️ C2, C13 | Misure di sicurezza aggiuntive (§7) |
---
## Registro delle modifiche
| Versione | Data | Allineato a | Modifiche |
|---|---|---|---|
| 0.4 | 27/09/2026 | `richiesta.md` v0.4 | Prima stesura, ricostruita da `architettura.md` e dai §5–6 di `flussi-di-lavoro.md` della cartella `software.old` (24/09/2026). Rispetto all'originale: lo stack passa da scelta fatta a confronto con orientamento (B1.10); codici allineati al repository (RNF → RT, circolari in M8, valutazione del volontariato in M9, fasi secondo D3); tolti Redis, la predisposizione per più studi e l'adattamento a smartphone, che nessun requisito chiede; aggiunti la row-level security (D12), la firma simulata in sviluppo e la risposta (c) di Q19 tra i punti che possono cambiare l'architettura |
| 0.4.1 | 27/09/2026 | `richiesta.md` v0.4 | Verifica sulle fonti: la conservazione digitale è richiesta da [D], quindi Q9 decide solo se va fatta a norma (prima sembrava facoltativa); il CSV nell'importazione è segnato 🔸 perché le fonti citano solo Excel e PDF |
| 0.4.2 | 27/09/2026 | `richiesta.md` v0.4 | Nome di M3 allineato a `richiesta.md` v0.4.4 ("Anagrafica stakeholder", da [X]) |
| 0.4.3 | 27/09/2026 | `richiesta.md` v0.4 | §1: il vincolo "un solo sviluppatore" non indica più chi segue la manutenzione dal secondo anno (richiesta di Davide) |
| 0.4.4 | 27/09/2026 | `richiesta.md` v0.4 | §7: tolta l'indicazione che D11 decida le "ore di manutenzione" dal secondo anno; D11 decide solo che la gestione tecnica resta a Davide con contratto separato, non termini e ore, ancora aperti |
2026-09-27 19:41:16 +02:00
| 0.4.5 | 27/09/2026 | `richiesta.md` v0.4 | §6: B1.10 orientata su Django (conoscenza di Davide), non ancora decisione (D); indicate le librerie per colmare coda/pianificatore e notifiche |
---
## Stato
2026-09-27 19:41:16 +02:00
- **Fase corrente:** analisi dei requisiti; architettura in bozza v0.4.5.
- **Decisioni prese:** D12 (PostgreSQL, migrazioni, row-level security); firma simulata in sviluppo (`costi-ricorrenti.md`). B1.10 orientata su Django, non ancora decisione. Il resto è proposta 🔸.
- **Prossimo passo:** Davide conferma B1.10 (Django) come decisione formale e le proposte 🔸; quelle approvate diventano decisioni in `richiesta.md` §7 (versione 0.5, con allineamento dei documenti derivati).