VibeInspect.aiBlog

Il codice compila. Ma con Bolt il tuo webhook può essere riprodotto

VibeInspect.ai · 23 agosto 2026 · 6 min di lettura

  • Bolt
  • vibe-coding
  • sicurezza
  • webhook
  • idempotenza

Il codice che compila non è ancora una prova

Un nuovo benchmark mette sotto pressione gli agenti di coding su un terreno che le demo tendono a evitare: refactor complessi, distribuiti su più file e con tolleranza quasi nulla per i cambiamenti di comportamento.

L’articolo Most coding agent benchmarks skip large-scale refactoring. Not this one. racconta SWE-Bench ProMax, una raccolta di 170 attività reali in sette linguaggi. Il miglior risultato riportato arriva al 41,2% di risoluzione. Il messaggio per un founder è semplice: compilare, superare un test o produrre una diff ordinata non dimostra che il sistema conservi le proprietà importanti.

Questa distinzione conta anche fuori dai grandi refactor. Un’app può funzionare nel caso felice e avere un comportamento sbagliato quando una richiesta viene ripetuta, arriva fuori ordine o viene ritardata dalla rete.

Cosa significa se il tuo codice l’ha scritto Bolt

Immagina di aver usato Bolt per aggiungere pagamenti, notifiche o sincronizzazione tra servizi. Per ricevere gli aggiornamenti, hai inserito un endpoint webhook: il provider invia un evento, il tuo backend verifica la richiesta, aggiorna il database e mostra lo stato corretto nell’interfaccia.

Il flusso sembra lineare. L’evento arriva, il codice risponde 200, il record cambia e il test passa.

Il buco concreto è un altro: il webhook non è idempotente e accetta più volte lo stesso evento.

Un provider può ritentare l’invio se la risposta tarda, se la connessione cade o se riceve un errore temporaneo. Un client può ripetere una richiesta. Un attore che abbia intercettato una richiesta valida può provare a riprodurla. Se il tuo handler aggiorna lo stato o crea un effetto collaterale senza registrare e bloccare l’event_id già processato, lo stesso evento può produrre più addebiti, più email, più crediti o più movimenti di stato.

Non serve che Bolt abbia generato una funzione evidentemente sbagliata. Il codice può essere ben tipizzato, leggibile e coerente con il resto del progetto. Il problema vive nella relazione tra firma, identificatore dell’evento, transazione sul database e risposta del servizio.

La differenza tra “funziona” e “regge” sta qui: il primo test invia un evento una volta; il secondo lo invia due volte, in ritardo o mentre un’altra elaborazione è ancora in corso.

Perché ora ti serve un audit del repository

Qui l’audit non serve a leggere ogni riga per sport. Serve a produrre una risposta verificabile a una domanda precisa: se lo stesso webhook arriva due volte, il repository impedisce davvero il secondo effetto collaterale?

Per rispondere bisogna seguire l’intero percorso:

  • quale route riceve il webhook;
  • se la firma viene verificata prima di usare i dati ricevuti;
  • quale campo identifica univocamente l’evento;
  • se l’identificatore viene salvato o confrontato prima dell’azione;
  • se il controllo avviene dentro una transazione;
  • cosa succede quando due richieste identiche arrivano quasi insieme;
  • se il provider può ritentare e come viene gestita la risposta;
  • se esistono endpoint alternativi che applicano meno controlli.

Un semplice controllo sulla presenza di verifySignature() non basta. La funzione potrebbe essere chiamata dopo l’aggiornamento del database, oppure verificare la firma ma non impedire la ripetizione dell’evento. Anche una tabella webhook_events non prova nulla se manca un vincolo univoco o se il controllo e l’effetto collaterale avvengono in operazioni separate.

Un audit VibeInspect analizza lo ZIP del repository e restituisce un PDF con score e verdetto. Nel piano Diagnostic, il report aggiunge file, righe ed evidenze per collegare route, verifica, persistenza dell’evento e azione eseguita.

Il risultato utile non è “abbiamo una funzione per i webhook”. È un verdetto: PASS, se il flusso impedisce duplicazioni in modo coerente, oppure FAIL, se esiste un percorso concreto che consente di applicare due volte lo stesso evento.

Questo è il passaggio che spesso manca nei progetti costruiti velocemente. L’agente ha trasformato il requisito in codice. Nessuno ha ancora dimostrato che il codice mantenga il comportamento corretto quando entra in gioco il tempo.

L’evidenza deve seguire l’effetto collaterale

Un audit serio deve distinguere tra un sospetto e una prova.

Trovare una chiamata a createPayment dentro un handler non dimostra automaticamente una vulnerabilità. Potrebbe esserci una transazione con chiave idempotente nel service sottostante. Allo stesso modo, trovare un controllo su event_id non basta: bisogna verificare che il record venga creato in modo atomico e che una seconda richiesta riceva un esito sicuro senza ripetere l’azione.

La catena di evidenze dovrebbe mostrare almeno quattro passaggi: ingresso dell’evento, autenticazione della richiesta, verifica della sua unicità e modifica dello stato. Se uno di questi passaggi è solo implicito, distribuito in un middleware non sempre applicato o affidato al client, il report deve renderlo visibile.

Il rischio aumenta quando l’handler esegue più operazioni: aggiorna un ordine, assegna crediti e invia una notifica. Anche se il database evita il doppio aggiornamento, una chiamata esterna potrebbe essere ripetuta. Il verdetto deve quindi considerare il comportamento dell’intero percorso, non solo la query principale.

Cosa un linter non vede

Un linter controlla regole locali: sintassi, tipi, import, formattazione e alcuni pattern conosciuti. Non sa necessariamente che un provider ritenta una consegna dopo un timeout. Non conosce il significato operativo di un event_id né stabilisce se un effetto collaterale è ripetibile.

Non vede sempre la differenza tra una transazione atomica e due chiamate consecutive. Non ricostruisce da solo il confine tra il codice che verifica una firma e quello che invia una richiesta a un servizio esterno. Può segnalare una promessa non gestita, ma non dirti se due webhook simultanei possono creare due ordini.

Anche i test possono tranquillizzarti troppo. Un test che invia un evento valido una sola volta dimostra il percorso nominale. Non dimostra cosa succede quando:

  • lo stesso evento viene consegnato due volte;
  • due richieste arrivano nello stesso momento;
  • il database salva il record ma la risposta non parte;
  • l’API esterna risponde lentamente;
  • la firma è valida ma l’evento è già stato processato.

Il linter ti dice che il codice rispetta certe regole. L’audit ti dice se il repository contiene un buco nel comportamento reale del prodotto.

Cosa fare questa settimana

  1. Scegli un solo webhook che modifica denaro, stato, accessi, crediti o notifiche.
  2. Elenca route, middleware, service e chiamate esterne coinvolte.
  3. Verifica che la firma venga controllata prima di usare il payload.
  4. Identifica il campo univoco dell’evento e controlla che abbia un vincolo lato database.
  5. Invia lo stesso evento due volte e osserva se l’effetto collaterale si ripete.
  6. Simula due richieste contemporanee e un timeout dopo il commit.
  7. Controlla che eventuali retry del provider siano gestiti senza duplicare l’operazione.
  8. Se hai usato Bolt e non sai formulare un verdetto sul flusso, esegui un audit Diagnostic prima del prossimo rilascio.

Non devi smettere di usare Bolt. Devi smettere di usare 200 OK come prova che il percorso sia corretto. Il codice generato dall’AI può portarti rapidamente a una prima versione. La responsabilità tecnica comincia quando devi dimostrare cosa succede al secondo invio, alla richiesta fuori ordine e alla connessione che cade nel momento peggiore.

Carica lo ZIP del repository e ottieni un verdetto con evidenze tecniche: avvia un audit Diagnostic.

Domande frequenti

Che cos’è un webhook non idempotente?

È un webhook che produce di nuovo lo stesso effetto ogni volta che riceve un evento già elaborato. Un retry può quindi creare duplicazioni, come più addebiti o più notifiche.

Un webhook può essere ripetuto anche se il codice risponde 200?

Sì. Il provider può ritentare se la risposta arriva in ritardo o la connessione si interrompe. Una risposta 200 non dimostra che l’evento sia stato registrato una sola volta.

Un linter rileva sempre i problemi di idempotenza?

No. Un linter può segnalare alcuni pattern, ma non ricostruisce il rapporto tra retry, transazioni, vincoli univoci ed effetti collaterali esterni.

Quale piano VibeInspect è adatto a un possibile problema nei webhook?

Il piano Diagnostic, perché include file, righe ed evidenze per verificare il percorso tra endpoint, autenticazione, database e azione eseguita.