Quaranta pagine su come guardare
La frase era: «questi dati ci servono nel gestionale».
A dirla era il responsabile operativo di un noleggiatore di taglia media: qualche centinaio di macchine in flotta, tre filiali, un gestionale cresciuto in casa negli anni, due persone in tutto sull’IT. Non un’azienda tecnologica. Un’azienda che porta macchine nei cantieri e le riporta indietro, e che sul software ha esattamente le risorse che servono a tenerlo in piedi.
Nel gestionale c’era già tutto il resto: contratti, trasporti, manutenzioni programmate, fatturazione. Mancavano le macchine: ore motore, cicli di lavoro, allarmi, stati. Un campione ogni tre minuti, per ogni macchina connessa. Quei dati esistevano ed erano completi. Erano sul portale del costruttore, dietro un login, in una pagina con un grafico e un pulsante di esportazione.
Il punto non era la fatica in sé. Era che la registrazione delle ore dipendeva dalla buona volontà di una persona che aveva anche altro da fare, e a cui scrivere numeri su un foglio non piaceva né veniva rapido. Quindi slittava, regolarmente, dietro a cose più urgenti, e quando serviva, i dati erano quelli che qualcuno si era ricordato di annotare.
La posta in gioco non era la comodità, era il contratto. Il noleggio si fattura a ore di utilizzo, e le ore le dichiarava il cantiere. La manutenzione si programma sulle ore, e quelle stesse ore le trascriveva a mano qualcuno che apriva il portale, filiale per filiale, quando se ne ricordava. Le contestazioni non erano tante. Ma arrivavano quasi sempre insieme ad altre difficoltà: quando in cantiere qualcosa va storto si discute su tutti i fronti contemporaneamente, e le ore diventano uno dei fronti. Ogni contestazione diventava mezza giornata di ricostruzione, nel momento peggiore per averla. Ogni intervento saltato era una macchina che tornava rotta prima del previsto, e nessuno collegava le due cose perché non c’era un posto dove i numeri stessero insieme.
Nessuno stava misurando quel costo, perché era distribuito su chiunque capitasse.
Abbiamo chiesto al costruttore l’accesso via API. La risposta è arrivata come allegato: il manuale utente del portale, con gli screenshot. Nessuna cattiveria e nessuna trattativa: semplicemente, per come era pensato quel prodotto, la domanda non aveva senso. I dati si guardano. Se li vuoi altrove, li guardi e li riscrivi.
E qui comincia il lavoro vero, che non è tecnico: decidere se questa cosa si fa, e cosa significa farla.
Il tentativo che fanno tutti
La prima cosa che ho provato è la prima che prova chiunque: prendere l’indirizzo del portale, cercare un endpoint di autenticazione, mandargli utente e password.
Non funziona. Il password grant OAuth2 è disabilitato sull’endpoint OIDC (il server risponde che il client non è abilitato agli accessi diretti) non per una configurazione sbagliata, per una scelta di chi ha montato il sistema. E la pagina di login è un’applicazione JavaScript a pagina singola, non un documento da compilare e spedire. Non c’è un form da inviare, c’è del codice che parla con un endpoint OIDC.
Ho passato qualche ora a provare varianti. È il punto in cui è facile perdere una settimana: ogni tentativo è abbastanza vicino al successo da far credere che manchi un dettaglio.
Smettere di attaccare l’API
La svolta non è stata tecnica ma di metodo: smetti di cercare l’API che vorresti e guarda quella che c’è già.
Il portale funziona. Ogni volta che qualcuno apre quel grafico, qualcosa risponde con dei numeri. Non serve indovinare l’interfaccia: basta leggere una conversazione che avviene comunque, decine di volte al giorno, ogni volta che un capocantiere controlla una macchina.
Venti minuti con le DevTools del browser hanno raccontato quello che il manuale non diceva in quaranta pagine. Il portale era una superficie: sotto c’era una piattaforma OIDC, con un altro nome, che il costruttore aveva integrato e rivestito con i propri colori. Le chiamate non andavano al portale, andavano a quell’endpoint. E quell’endpoint un’interfaccia programmabile ce l’aveva: solo, non era documentata per i clienti, perché dal punto di vista commerciale non esisteva.
Da lì in poi non è stato reverse engineering nel senso avventuroso del termine. È stato leggere: quali chiamate, in che ordine, con quali parametri, cosa torna indietro.
Quindici minuti alla volta
Restava il primo accesso, e la scelta è stata accettare il confine invece di forzarlo: un browser headless (Chromium pilotato da Playwright) che fa il login una volta e restituisce le credenziali di sessione. Da quel momento il browser non serve più: l’access token dura quindici minuti e si rinnova con polling HTTP, e la catena di rinnovi regge circa otto ore.
Otto ore sono un turno. Il processo poteva partire la mattina, raccogliere tutto il giorno e chiudersi da solo.
Il resto è venuto in fretta. Ore motore, cicli, allarmi, stati. Nel giro di pochi giorni i dati arrivavano nel gestionale, aggiornati quasi in tempo reale, sovrapponibili a quelli del portale. Funzionava.
I numeri erano sbagliati
Funzionava per modo di dire.
Ce ne siamo accorti per una via traversa: una macchina risultava avere ore motore che non stavano in piedi rispetto ai cicli di lavoro registrati. Non un valore assurdo: un valore strano. Il tipo di anomalia che su una macchina vera può benissimo essere una macchina che sta lavorando male, e infatti la prima ipotesi è stata quella.
Il problema era nell’integrazione, e la causa è di quelle che fanno arrabbiare per quanto sono semplici. Quando chiedi più grandezze insieme, l’endpoint non risponde nell’ordine in cui le hai chieste: le riordina secondo un criterio suo. Io avevo fatto la cosa naturale: prima grandezza chiesta, prima colonna della risposta JSON.
Così le ore motore finivano nella colonna dei cicli. Tutti valori nell’intervallo giusto. Tutti perfettamente plausibili.
Nessun errore, nessuna eccezione, nessun valore nullo, nessuna riga di log. Un sistema che dichiara successo, restituisce dati completi, e li mette nel posto sbagliato.
L'endpoint riordina le serie secondo un criterio suo. Mappando per posizione, ogni valore finisce sotto l'etichetta sbagliata, e restando tutti nell'intervallo plausibile, nessun controllo automatico distingue il risultato da uno corretto.
Perché nessun test lo avrebbe preso
È la parte che vale la pena portarsi a casa, perché non riguarda questo progetto.
Se avessi scritto dei test su quell’integrazione (e ne avevo) sarebbero stati verdi. Un test su un sistema simulato verifica che il tuo codice legga correttamente una risposta che hai scritto tu. E tu la scrivi nell’ordine che hai in testa. Il sistema simulato conferma il tuo modello mentale, che è esattamente la cosa che non serve verificare.
Solo il sistema vero riordina. Solo il sistema vero si comporta in un modo che non avevi previsto, perché se l’avessi previsto, l’avresti già gestito.
È un argomento su cosa i test provano, non contro i test. Un’integrazione con un sistema di terzi ha una classe di errori che vive interamente nello spazio fra quello che credi che l’altro faccia e quello che l’altro fa. Quello spazio si copre in un modo solo: guardando i dati veri e chiedendosi se hanno senso. Da noi ha funzionato un controllo di coerenza fisica (ore di funzionamento che devono stare in un certo rapporto con i cicli) non un test.
Dove finisce il lavoro
C’è una domanda che vale la pena farsi prima di essere contenti del risultato: su cosa poggia tutto questo?
Poggia su un’osservazione. Non su un contratto, non su una documentazione, non su un impegno di nessuno a non cambiare le cose. Il costruttore non sa che quel processo esiste, e non ha nessun obbligo verso di lui: il giorno in cui aggiorna il portale, qualcosa smette di funzionare, e nessuno avvisa.
Questo non rende il lavoro sbagliato. Lo rende una cosa che va dichiarata per quello che è, e la scelta successiva discende da lì: non ho costruito sorveglianza, non ho promesso continuità, non ho lasciato credere che fosse un’integrazione come le altre. Ho scritto quanto durerà, per quanto ne so, e cosa succede quando finirà.
Il modo elegante di chiudere questa storia, del resto, è chiedere al costruttore se un’interfaccia ufficiale esiste. Costa una mail, e toglierebbe di mezzo sia l’osservazione sia il browser. È rimasto fra le cose da fare, ed è la prima.
Il deliverable non era il codice
Alla fine il gestionale ha ricevuto le ore, i cicli e gli allarmi senza che nessuno li trascrivesse più a mano. Le contestazioni sulle fatture si chiudono guardando una schermata invece di ricostruire una settimana. La manutenzione si programma sui numeri veri.
Ma la cosa che ho consegnato con più cura non è l’integrazione.
È un documento. Come funziona il protocollo, per quanto ne so. Perché il primo accesso passa da un browser, e cosa succederebbe se il costruttore cambiasse quel flusso. Perché le risposte vanno mappate per nome e mai per posizione: con la storia dei numeri nella colonna sbagliata scritta per intero, così che il prossimo non debba ritrovarla da solo. Cosa non è stato costruito, e per quale ragione: non per mancanza di tempo, per scelta. Cosa andrebbe sorvegliato. Cosa resta aperto.
È scritto per qualcuno a cui non sarò io a spiegarlo. Perché un’integrazione basata sull’osservazione di un sistema di terzi ha una data di scadenza che nessuno conosce: il giorno che il costruttore aggiorna il portale qualcosa smette di funzionare, e in quel momento la differenza fra un problema di mezza giornata e una riscrittura da zero è tutta lì dentro.
Il cambiamento che si vede sta nella fiducia, non nei numeri. Il sistema dà riscontro mentre le cose accadono, e quello che viene prodotto si guarda quasi in tempo reale: serve a chi noleggia per sapere come stanno andando le macchine, e serve al cliente finale che ha un resoconto continuo invece di un consuntivo alla fine.
E c’è una conseguenza che vale più della comodità: i dati non vengono prodotti quando servono, vengono costruiti volta per volta secondo un processo definito. È la differenza fra un numero che qualcuno ricostruisce a posteriori e un numero che c’era già prima che nascesse la discussione. Quando arriva una controversia, quella differenza è tutto.
Un’integrazione è finita quando qualcun altro può portarla avanti da solo, compresi i punti dove hai deciso di non arrivare.
Il caso è reale. Sono stati rimossi i nomi del costruttore, del cliente e dei modelli coinvolti; tempi e scene sono compressi e ricostruiti. Restano fedeli il vincolo sul primo accesso, il riordino silenzioso delle risposte, e il perimetro dichiarato nel documento consegnato.