Quando aggiungi un connettore OAuth a un’app che promette di girare completamente offline, succede qualcosa di interessante: i tuoi principi iniziano a negoziare con la realtà. Non è una contraddizione, ma un’occasione per fare scelte consapevoli. La storia di come abbiamo integrato Google Calendar in Private Mind, un chatbot locale con modello Gemma, è esattamente questo: una successione di decisioni che aveva poco senso sulla carta e molto senso davanti a chi il software lo doveva davvero usare.
Il primo istinto di qualunque ingegnere di fronte a “integra OAuth2 con Google” è uno solo, prendi una libreria consolidata, plug-and-play. Esistono google-auth-oauthlib e google-api-python-client, ben mantenute, con una comunità enorme. Ma qui è cominciato il vero ragionamento. Private Mind è costruito esplicitamente per funzionare senza dipendenze pesanti. È disegnato per essere pacchettizzato in un eseguibile standalone con PyInstaller, distribtuito come zip, eseguito offline. Aggiungere google-api-python-client avrebbe portato dentro un albero di dipendenze, google-auth, httplib2, google-auth-httplib2, uritemplate, in gran parte ereditate da un’era precedente del web. Non per sé disastrose, ma incompatibili con la filosofia del progetto.
Scriviamo OAuth2 a mano
Non è un gesto romantico né un’affettazione. È una decisione pragmatica che partiva da una costrizione reale, il progetto usava già urllib.request e json da stdlib per page_fetch.py. Un secondo stack HTTP avrebbe significato duplicazione. Invece, usare le stesse funzioni per parlare con Google OAuth ha voluto dire una sola cosa, scrivere le 315 righe di google_oauth.py, testare il flusso authorization-code + PKCE con quattro scenari critici, documentare le tre eccezioni che il backend di Google può restituire in forme diverse. È stato meno lavoro di scegliere quale libreria, studiarla, mappare il suo codice di errore a quello di Google, decidere come integrare le sue sessioni in una app che di sessioni non ha bisogno.
Sessioni
Private Mind non usa cookie di sessione Flask né un secret configurato globale. Avrebbe senso aggiungere entrambi, per tracciare il flusso OAuth in corso. Ma il progetto ha un utente solo davanti a un browser solo, lo stesso presupposto già usato per model.model_state, il dict di modulo dove vive lo stato del caricamento del modello. Abbiamo applicato lo stesso pattern, lo state e il code_verifier PKCE generati dal pulsante “Connetti” vivono in una variabile di modulo per i dieci minuti di validità. Non è scalabile. Ma è coerente. E elimina la necessità di decidere dove mettere il secret della sessione, una scelta che nelle app single-user avrebbe fatto più male che bene.
Modello di accesso ai calendari
Poi c’è il modello di accesso ai calendari. La prima versione interrogava solo calendars/primary/events, il calendario principale dell’account, quello legato all’identità di Google di chi usa l’app. Tutto regolare. Fino a quando un utente con quattro calendari (Lavoro, Personale, Urgenti & To-Do, più uno condiviso da un’altra persona) ha cliccato “Aggiungi calendario” e ha visto comparire solo gli eventi da Lavoro. Silenziosamente. Senza errore. Gli altri tre calendari erano invisibili.
Qui è successo qualcosa di cruciale: i test non l’hanno preso, perché i test simulavano un’unica risposta HTTP con un calendari fake. Un utente vero ha scoperto il buco. Abbiamo dovuto correggere riscrivendo il flusso, prima interrogare calendarList per scoprire tutti i calendari a cui l’utente ha accesso, poi leggerli tutti quelli che ha spuntato nell’interfaccia di Google Calendar (il campo selected: true che marca “mostrato nella UI”). Gli eventi di calendari diversi si fondono in un’unica sequenza cronologica, ognuno etichettato [Nome del calendario] così chi legge sa da dove viene ogni impegno.
Quella correzione ha aggiunto tre API calls a uno scenario banale (contro una sola prima), ma ha anche rivelato un principio che come architect vale la pena ricordarsi, il tetto sulle richieste HTTP non è opzionale quando l’utente ha decine di calendari (festività, compleanni, calendari condivisi accumulati nel tempo). Abbiamo messo un limite di dieci. Non è configurabile. È una decisione presa una volta, comunicata nei commenti del codice, e basta.

Il miglior progettista
Per Private Mind, offline non vuol dire “non parlare mai con il web”, ma “non dipendere dal web per funzionare”. Il connettore Google Calendar è un’aggiunta consapevole, opt-in, che l’utente attiva quando ne ha bisogno. Richiede credenziali, è geograficamente separato dal resto, è testato come se fosse un modulo esterno. E quando l’ha usato un utente vero, ha rivelato le cose che nessun test avrebbe mai trovato.
Non è una lezione sulla superiorità del codice scritto a mano. È una riflessione su come le costrizioni reali, uno zip standalone, nessune sessioni Flask, un utente solo, finiscono per essere il miglior progettista che puoi avere. Ti forzano a scrivere meno, a scegliere meglio, e a riconoscere quando il primo tentativo di un utente reale ti sta dicendo che hai sbagliato qualcosa.
Se l’articolo ti è piaciuto restiamo in contatto su linkedin a: https://www.linkedin.com/in/andreatonin/
| Editorial Manager at Pills for Nerds | CTO & Technology Consultant |
Technology professional, editor and lifelong nerd with over 30 years of experience in the digital and innovation sectors. I work as a CTO and technology consultant, designing complex and scalable software ecosystems, and I am also active in IT education and professional training. Alongside my technology career, I serve as Editorial Manager and contributor at Pills for Nerds, online publication covering video games, game development, emerging technologies, artificial intelligence, digital culture and industry events. In my editorial role, I coordinate content planning and contribute articles, interviews, event reports and in-depth features. You can learn more about my consulting work at lucedigitale.com and connect with me on LinkedIn

















