Duckburg Smart City
Un comune digitale completo, costruito per intero e pubblicato aperto. Portale in stile Designers Italia con il suo CMS, identità digitale SPID e CIE con la federazione vera, e un assistente che risponde al cittadino solo su contenuti certificati dell'ente.
Gira su un comune immaginario, il Comune di Paperopoli. È immaginario il comune, non il software.
Tre parti, un solo comune
- Il portale e il suo CMS. Le pagine del Comune secondo il modello Comuni, e il backoffice dove la redazione le scrive.
- L'identità digitale. Un Relying Party OIDC Federation che parla il profilo SPID/CIE italiano, e il portale dei servizi al cittadino che ne consuma l'accesso.
- ChattyDuck. L'assistente virtuale, e la catena che lo alimenta: un corpus di contenuti certificati esposto tramite un protocollo aperto.
ChattyDuck è la parte più visibile, ma è una parte.
L'assistente, in una riga
Il system prompt definisce solo il comportamento del modello. I contenuti risiedono unicamente nel corpus. Se un dato non è nella fonte, l'assistente non lo inventa: dice che non è nelle fonti.
I modelli, Gemini e Claude, citano identificativo e versione di ogni passaggio che recuperano.
Il contenuto nasce dove viene scritto
Il corpus non è un file: è un servizio, alimentato da chi il contenuto lo scrive davvero. La redazione pubblica una scheda nel CMS e la vede comparire nelle risposte dell'assistente, senza che nessuno tocchi un file.
Fra il CMS e il corpus c'è una regola sola, e regge tutto il resto. Un dato diventa un fatto solo se nel CMS era già strutturato. Il costo di un servizio, una scadenza, un orario: quelli sono attributi, interrogabili. Il resto resta prosa, e la prosa non viene mai spremuta per estrarne fatti. Un'espressione regolare che indovina un importo dentro un paragrafo produce un dato che sembra certificato e non lo è.
Ogni contenuto porta con sé il proprio periodo di validità. Una scadenza passata non viene presentata come attuale: viene detta come scaduta.
Attaccarlo a un altro CMS
Il corpus non conosce il CMS di Paperopoli. Parla il vocabolario del modello Comuni: tipi di contenuto, attributi, relazioni, sezioni. Lo schema è pubblicato dal servizio stesso.
Per un altro CMS si riscrive solo l'adattatore, che è il pezzo più piccolo della catena. Il corpus verifica quello che riceve e risponde con l'elenco puntuale di errori e avvisi, così un adattatore si corregge finché non è pulito senza mai toccare il corpus vivo. E non è detto che sia .NET: il corpus si parla in HTTP e JSON.
Due modelli, due modi di collegarsi
Questa è la parte che vale la pena guardare da vicino.
- Gemini non parla MCP in modo nativo. Il portale fa da ponte: traduce i tool del server nel formato che Gemini capisce ed esegue le chiamate per suo conto.
- Claude parla MCP in modo nativo. Si collega direttamente all'endpoint pubblico del server, senza ponte. Gli basta l'indirizzo.
Lo stesso corpus, due strade diverse. Per Gemini ho scritto il ponte. Per Claude non è servito. Dove lo standard aperto è supportato davvero, il lavoro di integrazione sparisce.
Chiunque può collegarsi
Il corpus non è chiuso dentro il mio portale. Qualunque client MCP può consumarlo, puntando all'endpoint pubblico del server. Nella pagina dell'assistente c'è la configurazione pronta da copiare per collegare il proprio chatbot.
L'ente espone la fonte una volta sola. Poi ci si collega chi vuole, con l'assistente che preferisce.
Quando la fonte non c'è
Un dettaglio piccolo che dice come è pensato il resto.
Se il corpus non è ancora allineato, gli strumenti non restituiscono un elenco vuoto: restituiscono un errore che dice al modello di avvisare l'utente. Un elenco vuoto il modello lo leggerebbe come "questa informazione non esiste", e risponderebbe al cittadino che il Comune non se ne occupa.
Un elenco vuoto, in una risposta che si presenta come certificata, è una bugia.
Identità digitale: SPID e CIE
Qui non c'è niente di simulato tranne gli interlocutori.
Il Relying Party implementa il profilo italiano OpenID Connect Federation per intero: catena di fiducia risolta a ogni accesso, entity configuration firmata e pubblicata, registrazione automatica del client, richiesta di autorizzazione in un request object firmato, PKCE, autenticazione con private_key_jwt, UserInfo cifrata, refresh token e logout iniziato dal RP.
Non è un mock del login SPID. È il protocollo.
Dall'altra parte della federazione stanno il Trust Anchor e l'OpenID Provider CIE: sono le immagini ufficiali AgID, italia/spid-cie-oidc-django, fissate per digest così che l'ambiente sia riproducibile. Quindi non è il mio codice a dirmi che il flusso è corretto: è l'implementazione di riferimento che lo accetta. Il giro completo, accesso CIE, refresh e logout, è coperto da un test end to end.
Un dettaglio che mi diverte: gli enti centrali della federazione non sono il Comune, e non fingono di esserlo. Sono lo Stato immaginario di Palmipedia, con marchi e palette propri. AIDP al posto di AgID, BeccoID al posto di un gestore SPID privato, IPZP al posto del Poligrafico. La finzione è dichiarata, non nascosta.
Cosa serve per passare ai gestori veri: gli hostname, le chiavi, il trust mark rilasciato dall'autorità di federazione, l'onboarding presso AgID, e tre punti di codice da toccare, fra cui l'elenco dei provider mostrati nella pagina di accesso, che oggi non mostra di proposito i pulsanti dei gestori reali. Non è "solo configurazione", ed è onesto dirlo. Ma è distanza di adempimento, non di architettura.
Servizi al cittadino
Dopo l'accesso il cittadino entra nella propria area personale e trova i dati della sua identità digitale: nome, cognome, codice fiscale, e il pannello che dice con quale identità è entrato e chi la gestisce.
Poi la lista delle pratiche, che è vuota, e lo dice:
Non c'è ancora nulla qui: questo è il primo servizio online del Comune e le pratiche digitali arriveranno una alla volta.
Vale la pena essere precisi, perché è la differenza fra una demo e una promessa. Quello che è costruito è la catena di autenticazione, non i servizi. TARI online e certificati anagrafici sono schede annunciate, non funzionanti. Il portale dei servizi è un'applicazione separata dal portale informativo: i due si parlano con un token SSO firmato e a scadenza breve.
Costruire la porta prima delle stanze è deliberato. La porta è la parte difficile, e chi ha provato a farla sa perché.
Conformità, misurata
C'è anche un modulo che esegue il validatore ufficiale pa-website-validator-ng contro il portale e ne mostra il referto. La conformità al modello Comuni della misura 1.4.1 non è un'autodichiarazione in fondo alla pagina: è un punteggio che chiunque può rifare.
Come si prova
L'assistente è online. Le domande di controllo che dimostrano l'ancoraggio alla fonte sono queste:
- "Quando scade la prima rata della TARI?" risponde 30 aprile e cita il passaggio.
- "Quanto costa la mensa scolastica?" dà la fascia di tariffe di Paperopoli, citando la sezione dei costi.
- "Quali eventi ci sono?" elenca gli eventi validi, ognuno con il proprio identificativo.
- "Che giorno passa l'umido nel quartiere Vesuvio?" risponde che non è nelle fonti, perché quel quartiere non esiste.
- La stessa domanda posta a client diversi dà la stessa risposta, ancorata agli stessi passaggi.
Il login SPID/CIE si prova in locale: si alza la federazione con docker compose, tre container, e si entra con le credenziali dimostrative.
Cos'è vero e cos'è finto
È simulato il comune, e solo il comune. Le vie, i quartieri, le scadenze, e lo Stato di Palmipedia che gli sta intorno.
Il resto è reale: il CMS, il corpus, il protocollo MCP, la federazione OIDC, il validatore, i modelli e il modo in cui rispondono.
Tra Paperopoli e un comune vero cambia il contenuto, che è lavoro dell'ente e non informatica, e cambia l'adattatore, se il CMS è un altro. Il corpus, il server, l'identità e l'assistente restano quelli.
Il codice è pubblico, con licenza Apache 2.0: si può forkare e usare come base di un prodotto, anche commerciale. Provalo, aprilo, mettilo alla prova.