Ingegneria
Ventisei procedure, una sola app
Costruire uno strumento civico quando il contenuto appartiene a ventisei amministrazioni
0. Da dove viene questo testo
Non sono svizzero. Mi sono trasferito a Morges nel 2014 e nel 2026 ho avviato la procedura di naturalizzazione ordinaria, che nel Canton Vaud si chiude con un test scritto di conoscenze organizzato dal comune di domicilio. Ho costruito questa app perché mi serviva, e ho continuato perché le parti più difficili non erano quelle che mi aspettavo. Nell'agosto 2026 ho sostenuto io stesso quell'esame e l'ho superato con il massimo: 48 su 48. In aula, quella mattina, diversi altri candidati stavano usando l'app.
Questo è un testo di ingegneria, non la presentazione di un prodotto. Parla di cosa succede quando la cosa che consegni non è davvero software: è un'affermazione su fatti che appartengono a qualcun altro e che cambiano senza avvisarti.
1. Il problema, in una riga
La Svizzera non ha un test di naturalizzazione nazionale. La legge federale non ne prescrive nessuno, e ciascuno dei ventisei cantoni è padrone del proprio formato. Alcuni pubblicano un catalogo completo di domande. Altri pubblicano materiale di studio e nessuna domanda. Altri ancora valutano oralmente e non pubblicano niente. E in un cantone il test non è cantonale ma comunale: le domande che riceve un candidato dipendono da quale delle trecento comuni abita.
Il modello ingenuo, una banca di domande e un esame e un'app, crolla quindi nei primi cinque minuti. La forma reale sono ventisei procedure diverse, e dentro una di esse altre trecento.
Oggi l'app porta 13'497 domande d'esame per tutti e ventisei i cantoni, di cui 9'565 comunali: domande che esistono solo per un comune e sono inutili a tutti gli altri. Scegliere il comune non è dunque una preferenza. È la query.
2. Perché la parte difficile non è l'app
Un'app a scelta multipla è un fine settimana. Il lavoro sta in tutto il resto: ottenere materiale che ventisei amministrazioni pubblicano in formati diversi, in tre lingue, con i loro tempi; decidere cosa ciascun elemento sia davvero; e tenere tutto onesto per mesi mentre nessuno ti dice che qualcosa si è mosso.
Quattordici cantoni hanno oggi un catalogo proprio dentro l'app. Gli altri dodici ricevono il livello federale preso in prestito, a tempo di esecuzione, da un cantone che invece lo pubblica, e l'app lo dichiara sulla domanda stessa. Quella distinzione, questo è il materiale del tuo cantone contro questo è materiale federale che ti mostriamo perché il tuo cantone non ne pubblica, non è una nota a pié di pagina. È la differenza fra uno strumento di studio e uno strumento ingannevole.
3. La catena del contenuto, e cosa porta con sé una domanda
Ogni domanda dell'app porta la propria provenienza: da dove viene, come è stata ottenuta, in che data e contro quale impronta della fonte. La ripartizione dice onestamente quanto sia disomogeneo il panorama:
| Metodo | Domande |
|---|---|
| Interfaccia cantonale viva | 9'693 |
| Estrazione di testo da PDF pubblicati | 1'525 |
| Traduzione automatica, marcata come non ufficiale | 522 |
| Redatte a mano da materiale ufficiale pubblicato | 890 |
| Curate manualmente | 28 |
| Trascrizione manuale verificata | 290 |
| Materiale ufficiale di formazione online | 126 |
| Altre forme dichiarate | 423 |
Nessuna domanda dell'app è priva di un blocco di provenienza. Era un vincolo di progetto fin dall'inizio, ed è la ragione per cui il resto di questo documento è possibile.
Dove nessun catalogo esiste e le domande vanno scritte, non si tratta di composizione libera. Ogni domanda redatta porta un'ancora: una stringa ripresa alla lettera da un documento ufficiale pubblicato. In fase di generazione il programma cerca quella stringa nel corpus delle fonti, e su tre cantoni fallisce in modo duro se l'ancora non si trova. Nessun risultato, nessuna pubblicazione. Una domanda che non può indicare una frase in un documento ufficiale non parte.
La stessa disciplina vale per la certezza. I parametri d'esame, quante domande e quale soglia di superamento e quanta durata, non vengono affermati. Ciascuno porta un livello di certezza: ufficiale, stimato, dichiarato dall'ente, non pubblicato, non applicabile. Nell'insieme dei modelli cantonali, quarantanove di questi parametri sono marcati non pubblicato, perché il cantone davvero non li pubblica. Mostrarlo onestamente si è rivelato più convincente, per lettori istituzionali, di un numero dall'aria pulita.
4. La sorveglianza notturna, e il controllo che nessuno scrive
Le fonti si muovono. Un cantone ripubblica un PDF, rinumera una serie, corregge una risposta. Nessuno manda una notifica.
Tredici cantoni hanno quindi la loro fonte pubblicata verificata ogni notte da una procedura pianificata, a orari scaglionati. Ogni esecuzione scarica la fonte, ne prende l'impronta, la confronta con il riferimento memorizzato e si risolve in uno di cinque esiti: invariata, cambiata, fonte irraggiungibile, rigenerazione fallita, o scrittura in banca dati fallita. Un disturbo di rete passeggero è deliberatamente distinto da un guasto vero, perché trattare una connessione capricciosa come una fonte rotta produce allarmi che nessuno legge.
Ogni esecuzione aggiunge una riga firmata a un diario in sola aggiunta, su un ramo separato: l'orario, l'impronta della fonte, lo stato HTTP, la durata dello scaricamento e la revisione del codice eseguito. La riproducibilità non è un'affermazione, è un registro.
Ma il controllo verso cui indirizzerei un revisore è un altro, ed esiste per un fallimento. Il rilevatore confronta le fonti a monte con un riferimento memorizzato. Non pone mai l'unica domanda che conta dopo la pubblicazione: quello che stiamo servendo corrisponde ancora a quello che abbiamo approvato? Non corrispondeva, e un cantone ha servito sessantadue domande la cui correzione era stata approvata sei settimane prima e mai pubblicata. In silenzio. Niente nella catena era progettato per accorgersene.
Un secondo confronto gira quindi ora a ogni ciclo, compresi, anzi soprattutto, i cicli in cui non è cambiato nulla. Ricalcola l'impronta del contenuto dal testo della domanda, dalle risposte e dalla risposta corretta, invece di fidarsi dell'impronta registrata, così che un'impronta vecchia compaia come divergenza invece di nasconderne una. Un cantone che nessuno tocca è esattamente il posto in cui una divergenza resta ferma senza farsi notare.
5. Aggiornare senza passare dagli store
Un esame ha una data. Se il cantone di un candidato corregge una risposta tre settimane prima del test, un'app che può consegnare solo attraverso la revisione di uno store non è uno strumento di studio, è un rischio.
Il contenuto quindi non viaggia con il programma. Le correzioni approvate raggiungono i dispositivi attraverso un canale differenziale: all'avvio e al ritorno in primo piano il client chiede tutto ciò che sta oltre il proprio segnaposto e lo sovrappone al catalogo incorporato. Nessuna sottomissione, nessuna coda di revisione, nessuna attesa che gli utenti aggiornino.
Il numero, misurato in produzione questa settimana: su 12'744 domande pubblicate, 541, cioè il 4,2 per cento, sono state riviste almeno una volta dopo la prima pubblicazione e consegnate per questa via. La distribuzione è disomogenea e racconta la sua storia. Le quote maggiori: 148 in Vallese, 140 nel Vaud, 112 a Lucerna, 43 a Basilea Città, 36 a Neuchâtel, 27 a Zurigo, 24 a San Gallo. Le domande di un cantone sono alla quinta versione.
Due salvaguardie rendono tutto questo difendibile invece che avventato.
Niente si pubblica da solo. Quando viene rilevato uno scostamento la catena rigenera, scrive in banca dati e marca il cantone come in attesa di revisione. In quello stato il client rifiuta di sincronizzarsi: gli utenti continuano a vedere il contenuto approvato in precedenza. Il passaggio a in linea è sempre manuale, e alla catena è strutturalmente vietato farlo. In questo momento tutti e tredici i cantoni pubblicati sono in linea.
Niente viene sovrascritto in silenzio. Ogni modifica archivia per intero la versione precedente della domanda, testo e risposte e risposta corretta e formato, prima che arrivi quella nuova.
Il ciclo più rapido finora: una delegata all'integrazione di una regione germanofona ha segnalato che le risposte lunghe venivano troncate. La causa era nostra, e peggio che cosmetica: il troncamento colpiva la risposta corretta ma non i distrattori, così la risposta giusta era sistematicamente quella corta che finiva con i puntini. Un indizio, dentro un simulatore d'esame. La riparazione ha toccato 147 delle 280 righe di quel cantone nelle due lingue, e la produzione ha registrato il cambio di contenuto due minuti dopo l'approvazione della correzione, la stessa sera della segnalazione.
6. La trasparenza come funzione, non come pagina
La maggior parte delle app tratta la trasparenza come un documento. Qui è una proprietà a tempo di esecuzione, e si vede in tre punti.
Sulla domanda. Sotto ogni domanda, in esercitazione come in simulazione, il candidato vede da dove viene, se il formato è stato adattato dall'originale, se è presa in prestito dal corpus ufficiale di un altro cantone, se è stata tradotta, e un contrassegno di verifica che porta la data dell'ultimo controllo della fonte.
Prima dell'esame. La simulazione dichiara, cantone per cantone, quali dei suoi parametri sono ufficiali e quali stimati, e distingue la via scritta da quella orale, perché in diversi cantoni la valutazione reale è un colloquio e presentare una simulazione a scelta multipla come « l'esame » sarebbe falso.
In pubblico. Una pagina di trasparenza, in quattro lingue, enuncia gli impegni di servizio: fonti verificate ogni ventiquattro ore, aggiornamento ordinario entro sette giorni, correzioni che toccano la correttezza entro settantadue ore. Offre inoltre alle autorità cantonali di naturalizzazione, alla Segreteria di Stato della migrazione e a ricercatori accreditati l'ispezione del registro di verifica su richiesta scritta, evasa entro cinque giorni lavorativi.
Pubblicare un impegno di servizio su cui si può essere misurati è scomodo. È anche l'unica versione della trasparenza che significhi qualcosa.
7. Un solo sviluppatore, tredici versioni in diciotto settimane
Il primo commit è datato 12 aprile 2026. Il 2 maggio l'app era in produzione. Da allora: tredici versioni minori pubbliche fino alla 3.12, 243 compilazioni, e almeno una compilazione in 89 dei 142 giorni.
Quel ritmo è sostenibile solo per quello che ci sta sotto: 186 file di test automatici, 320 migrazioni di banca dati versionate, e una catena di contenuto che verifica il proprio risultato invece di fidarsene. L'interfaccia è tenuta a quattro lingue da un test che rifiuta di compilare se una lingua ha una chiave che le altre non hanno. Attualmente 3'426 chiavi, identiche in tutte e quattro.
Niente di tutto questo è eroico. È la conseguenza ordinaria del fatto che una persona sola non può tenere in testa lo stato di ventisei cantoni, e non dovrebbe provarci.
8. Gli agenti come utenti del sistema
Questo è il capitolo che non mi aspettavo di scrivere.
Buona parte di questo progetto è stata costruita con agenti di programmazione. La parte interessante non è che abbiano scritto codice. È che si sono rivelati utenti del sistema di produzione, e utenti costosi.
In un giorno di agosto il traffico in uscita dalla banca dati del progetto si ripartiva così: gli strumenti, cioè script e utilità interne e agenti che misuravano cose, producevano circa cinque volte il traffico di tutti gli utenti veri dell'app messi insieme. L'app non è mai stata il problema. Lo era misurare l'app. E ha spinto il progetto contro una soglia di fatturazione con una scadenza.
Il modo di fallire era preciso e, col senno di poi, ovvio. Un agente incaricato di verificare che un inserimento avesse funzionato rileggeva la tabella. Un agente a cui si chiedeva quante righe ci fossero scaricava le righe e le contava. Un agente incaricato di sapere se qualcosa fosse cambiato lo scaricava e confrontava. Ognuno di quei riflessi è ragionevole per un umano davanti a un terminale, e catastrofico a frequenza di macchina.
Ne è uscita una costituzione del repository, letta automaticamente all'inizio di ogni sessione di agente, il cui primo capitolo non parla di stile del codice. Dice: ogni query che lanci contro questa banca dati è fatturata. Poi le regole che ne discendono. Mai leggere righe per contarle, perché un conteggio e un peso e un'impronta stanno su una riga ciascuno. Mai selezionare tutte le colonne delle tabelle pesanti. Aggregare lato server e ricevere dieci righe invece di diecimila. Una sessione per compito, non una per comando, perché ogni nuova connessione paga un costo fisso di protocollo prima ancora che la query parta. E verificare una scrittura con dei numeri, mai con uno scarico.
Accanto sta una memoria di progetto persistente, un fatto per file, indicizzata, che porta le decisioni che un agente non può ricavare dal codice: quali ambienti si possono scrivere e a quali condizioni, quali correzioni sono già state tentate e sono fallite, quali parti della catena una sessione nuova non deve toccare da sola.
La lezione va oltre questo progetto. Siamo abituati a ragionare il costo di un agente in gettoni. In un sistema con un backend vero, il costo di un agente è anche il carico che mette sulla tua infrastruttura, e quel numero può schiacciare il primo. Nessuno mi aveva detto di misurarlo. La fattura sì.
9. Quanto costa davvero
L'infrastruttura in sé, backend e distribuzione e account per sviluppatori, gira nell'ordine di qualche centinaio di franchi all'anno. La voce dominante non è affatto l'infrastruttura: è lo strumento di intelligenza artificiale che fa gran parte della costruzione, un abbonamento che avrei comunque e che è condiviso con tutto ciò su cui lavoro. Attribuito per intero, l'intero esercizio si aggira sui tremila franchi all'anno. Attribuito strettamente a questo progetto, è una frazione.
Per quella cifra, nel momento in cui scrivo: 10'010 profili registrati, di cui 7'317 hanno effettivamente studiato o giocato, in venticinque dei ventisei cantoni.
Metto i numeri perché sono la parte che si fa più fatica a credere, e perché inquadrano la domanda vera. Non è una storia sul fare molto con poco come virtù. È che uno strumento civico su scala nazionale oggi può essere costruito e mantenuto da una persona sola, e che il vincolo si è spostato. Non è più la capacità ingegneristica. È se le istituzioni che possiedono il contenuto abbiano un modo di partecipare a tenerlo corretto, e a quella domanda nessun codice risponde da solo.
