modulo 04 / lezione 26
Architettura mentale di un'applicazione
Il confine fra client e server: cosa non spostare mai
Evitare architetture pericolose in cui dati sensibili, segreti o regole critiche finiscono nel posto sbagliato.
Il confine fra client e server: cosa non spostare mai
Il confine client/server non è un dettaglio: è un confine di fiducia. Tutto ciò che vive nel client è sotto controllo dell’utente, ispezionabile, modificabile, falsificabile. Tutto ciò che vive nel server è sotto il tuo controllo. Mettere la cosa sbagliata dal lato sbagliato è la sorgente principale di vulnerabilità nei prototipi generati.
Perché questa lezione conta
Il modello AI propone con frequenza configurazioni dove “vediamo se l’utente è admin” sta nel client, “validiamo email” è solo regex JS, “prezzo finale” arriva dal client. Ognuna di queste scelte sembra innocua e produce app che si bypassano in 30 secondi con DevTools. Una lezione di 60 minuti su cosa non spostare mai dalla parte sbagliata vale più di tre giorni di patching post-incidente.
Obiettivo operativo
Alla fine devi saper:
- distinguere cosa può/deve stare nel client vs nel server;
- riconoscere il “falso senso di sicurezza” della UI nascosta;
- revisionare una lista feature classificando ognuna sul confine giusto.
Nucleo della lezione
1. Cosa può stare nel client
Il client è la finestra dell’utente. Ha senso ospitare:
- Presentazione: layout, stili, animazioni, componenti UI.
- Stato temporaneo locale: form input in corso, dropdown aperti, tab attiva.
- Preferenze locali individuali: dark mode, lingua, layout sidebar (in localStorage).
- Validazione di aiuto: feedback immediato all’utente (campo email senza @ → “email non valida”). NON sostituisce validazione server.
- Ottimizzazioni UX: cache di dati ricevuti dal server, ottimismo (mostra subito, conferma dopo), debounce.
- Routing client-side: navigazione fra pagine senza full reload.
- Logica di rendering: filtraggio/ordinamento di dati già ricevuti dal client.
Pattern: il client è “un’interfaccia, non un’autorità”. Mostra, suggerisce, accelera. Non decide, non protegge, non valida con autorità.
2. Cosa deve stare nel server
Il server è la fonte di verità. Vivi qui:
- Segreti: API key, database password, JWT signing key, OAuth client secret. Mai nel bundle client.
- Autorizzazione reale: chi può fare cosa. Verificata su ogni richiesta, mai dedotta da claim del client.
- Validazione affidabile: ogni input dell’utente, anche già validato lato client. Anche dato derivato dal client (es. prezzo) va riverificato.
- Operazioni su dati sensibili: cambio email, cambio password, pagamenti, dati medici, finanziari.
- Logica di business critica: calcolo prezzo finale, applicazione sconti, calcolo tasse, verifica disponibilità.
- Generazione token/codici: auth token, password reset link, magic link. Mai generati dal client.
- Rate limiting: contro abusi, brute force, scraping. Implementato lato server.
- Logging di sicurezza: tentativi falliti, accessi sospetti, audit.
Pattern: tutto ciò che ha conseguenze sui dati o sulla sicurezza vive sul server, è verificato dal server, è log-ato dal server.
3. Il falso senso di sicurezza della UI
Errore frequente: pensare che nascondere = proteggere.
- Nascondere bottone “Delete” se non admin → utente fa request HTTP direttamente, server accetta. Bypass: 5 secondi.
- Disabilitare campo input → utente toglie attributo
disabledcon DevTools. - Verificare ruolo in
if (user.role === 'admin')lato client → utente modifica oggetto user con DevTools. - Validare email con regex client → utente disabilita JS o manda direttamente al server.
- “Non vede questo URL” perché non c’è link → URL è prevedibile o leggibile da network inspector.
Conseguenza: ogni regola che si fa rispettare solo lato client è teatro. La regola vera vive sul server.
UX e sicurezza sono compatibili: nascondi UI per pulizia + verifica server per sicurezza. Entrambi, non solo uno.
Procedura pratica
Per ogni feature nuova, classifica componenti:
- Lista cosa fa la feature.
- Per ogni elemento, chiediti: “se l’utente bypassa il client, cosa succede?”. Se la risposta è “succede comunque” → ok client. Se è “il sistema fa qualcosa che non doveva” → server.
- Identifica segreti: dove sono? Se nel bundle client → spostali subito.
- Identifica autorizzazioni: dove sono verificate? Se solo client → aggiungi server-side.
- Documenta confine: in commenti o file di progetto, quali responsabilità sono in client vs server.
Laboratorio guidato
Lista feature di una piccola app commerce (e-shop), classifica ognuna:
- Layout pagina prodotto → Client. Pura presentazione.
- Filtro prodotti per categoria (UI) → Client + Server (sorgente verità). Filtro client veloce su dati paginati dal server.
- Calcolo carrello (subtotale) → Client (display) + Server (verifica al checkout). Mostro subito, server riverifica con prezzi correnti.
- Applicazione codice sconto → Server. Mai validare sconto solo client.
- Verifica disponibilità prodotto → Server. Stock cambia, fonte = server.
- Pagamento (totale finale) → Server. Server calcola, server invia a gateway.
- Mostra/nascondi bottone admin → Client. Solo UX. Endpoint admin protetti server-side.
- Validazione email a iscrizione → Client (UX) + Server (verità). Client per feedback, server per sicurezza.
- Carrello in localStorage (utente non loggato) → Client. Preferenza locale. Al checkout sync con server.
- Rate limit “max 5 ordini/min” → Server. Solo server può applicarlo.
Replica per la tua prossima feature.
Output atteso
Tabella confine per le feature principali del tuo prossimo progetto. Allegata al prompt iniziale: il modello produce architettura coerente al primo colpo.
Studio passo passo
Studia questa lezione in tre passaggi, senza correre subito al prompt o al codice.
- Prima lettura: chiarisci l’obiettivo: evitare architetture pericolose in cui dati sensibili, segreti o regole critiche finiscono nel posto sbagliato. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
- Seconda lettura: trasforma i contenuti in domande operative:
- Cosa può stare nel client: presentazione, stato temporaneo, preferenze locali, validazione di aiuto.
- Cosa deve stare sul server: segreti, autorizzazioni reali, validazione affidabile, operazioni su dati sensibili.
- Il falso senso di sicurezza della UI: nascondere un bottone non equivale a impedire un’azione.
- Applicazione: svolgi il laboratorio: revisionare una lista di funzionalità e decidere per ciascuna se vive nel client, nel server o in entrambi. L’output da ottenere è: una tabella di confini architetturali da allegare ai prompt che coinvolgono sicurezza o dati.
Prima di passare alla lezione successiva, controlla di avere un artefatto concreto: una tabella, un prompt, una checklist, un mini report, un diff commentato o una decisione scritta. Nel vibe coding la comprensione resta astratta finché non produce una traccia verificabile.
Checklist di verifica
- so quali sono le 3-5 cose che assolutamente non devono finire nel client;
- so dare 5 esempi concreti di “falso senso di sicurezza UI”;
- ho classificato ogni feature significativa del mio progetto attuale sul confine;
- conosco la regola “client suggerisce, server decide”.
Errori comuni
Segreti nel bundle client. API key Stripe public OK; secret key MAI. Cerca in .env chiavi che NON vanno con NEXT_PUBLIC_ / VITE_.
Calcolo prezzo finale dal client. Mostralo, ma server riverifica al momento del pagamento. Mai fidarsi del totale che arriva via POST.
Ruolo nel JWT visto dal client come autorità. JWT può rivelare ruolo, ma server deve riverificare. Non delegare authorization al claim.
Filtri client su dati ricevuti senza filtro server. Client dice “voglio solo i miei post”; server deve già aver filtrato. Altrimenti l’utente con DevTools vede post di altri.
Validazione client come unica. Sempre doppia: client per UX (immediata), server per verità.
API che ritorna troppo. “GET /users” che torna tutti gli utenti con email + hash password. Anche se UI mostra solo nome, l’API leak dati. Server filtra ciò che torna.
Prompt di lavoro
Sto progettando questa feature: [descrizione]
Lista delle responsabilità che immagino:
[lista]
Per ognuna, classifica e motiva:
1. Dove vive (client / server / entrambi)?
2. Se entrambi: quale è la fonte di verità, quale è ottimizzazione UX?
3. Se l'utente bypassa il client, cosa succede? È un problema?
4. Ci sono segreti coinvolti? Dove?
5. Ci sono autorizzazioni? Dove sono verificate?
Segnala:
- ogni cosa che oggi metterei nel client e che dovrebbe essere nel server
- ogni dato che il server ritorna in eccesso (over-fetching)
- ogni regola validata solo lato client
Non scrivere codice. Output: tabella di classificazione + segnalazioni.
Esercizio finale
Apri DevTools (Network tab) di una piccola app web che hai sviluppato. Per ogni endpoint che chiami, chiediti: cosa succede se manipolo la richiesta o la risposta? L’app si rompe in modo controllato (errore chiaro, autorizzazione respinta) o in modo pericoloso (esecuzione di azione non autorizzata)? Le aree dove si rompe in modo pericoloso sono quelle dove il confine client/server è messo male. Lì lavorerai prima.