Audit interno di correttezza/difendibilità del framework eseguito su 4 dealer di piattaforme diverse (Matarese — DealerMAX, carecar.it — GestionaleAuto, achillimilano.it — Carmove, newcarshop.it — Labycar) e su brokermotors.it (non-DealerMAX). Trovati e fixati 15+ bug oggettivi nel framework. Aggiunte 3 trasparenze nuove e una migration view per nascondere dal listing pubblico gli scan con framework obsoleto.
Bug fix oggettivi nei check:
tech.server_leak: regex precedente flaggava x-powered-by con qualsiasi valore — anche un brand-name pulito senza versione (es. DealerMax). Refactored a regex stretta su versione dotted (1.2, 8.1, 2.4.41) + stack runtime names (PHP, Apache, nginx, IIS, Express, ASP.NET, Tomcat, Jetty, Node.js). Anni single-integer in brand strings (DealerMax 2026 Platform) NON sono flaggati. Spec: OWASP ASVS V14.4.2 — runtime/version disclosure.tech.http_version: HTTP/2 era penalizzato (0.9) rispetto a HTTP/3 (1.0), ma httpx (client di audit) negozia max HTTP/2 anche su server HTTP/3-capable via Cloudflare. Ora HTTP/2 e HTTP/3 entrambi 1.0 — HTTP/2 è production standard (RFC 7540), HTTP/3 emergente.tech.blocking_scripts: bug regex con \b dopo quote impediva il match di type="module". Gli ES modules sono non-blocking per spec HTML5 (deferred di default) ma il check li flaggava come blocking. Fix: regex senza word-boundary tail.tech.redirects: prima 1 hop = 0.9, ora 1.0. Google Search Central raccomanda esplicitamente il pattern apex→www o HTTP→HTTPS con 301: punire la best practice non era difendibile.seo.canonical: il check verificava solo HTTPS, NON l'host-match con la URL servita. Un canonical che punta a un altro dominio passava silenziosamente. Ora confronto stretto: canonical host ≠ served host → fail.seo.sitemap_vehicles: regex hardcoded di path canonici (/usato/, /vendita/, ecc.) falliva su slug fantasia (/showroom/, /vetrina-veicoli/, /le-mie-auto/). Strategia rivista: regex come fast-path zero-costo, fallback sampling JSON-LD di 5 URL deep dal sitemap che verifica @type: Vehicle/Car nel contenuto. Non si tenta più di indovinare lo slug: si verifica il fatto.machine.jsonld: il Tier 2 (Offer + availability + priceCurrency) veniva verificato facendo '"availability"' in html sull'HTML grezzo — falsi positivi su qualsiasi occorrenza nel body, copy, attributi data, ecc. Refactored: l'HTML è parsato come JSON-LD e i sub-flag vengono verificati sui nodi Offer reali (ricerca ricorsiva attraverso @graph annidato).ainative.robots_ai_ua: parsing del robots.txt aveva 2 difetti: (a) falsa positivà — un UA con Disallow: /admin/ veniva contato come allowlisted; (b) replace fragile su "disallow: /\n" falliva su Windows line-ending \r\n. Refactored: parsing strict riga-per-riga. Solo Disallow: / totale esclude un UA dall'allowlist.ainative.llms_txt: bug nello scoring del ramo YAML frontmatter — la formula contava has_h2 due volte (has_h2 + (has_h2 and has_optional)), gonfiando lo score per i file YAML rispetto al markdown puro. Fix: has_h2 + has_optional indipendenti.ainative.link_rel_llms: il check ritornava axis="ai" mentre il loop di aggregazione iterava solo su ("tech", "seo", "machine", "ainative"). Risultato: il check veniva eseguito, esposto nelle evidenze, ma NON contava in nessun asse. Fix: axis="ainative".- Pesi variabili a runtime in 4 check (
llms_full, ai_txt, plugin_manifest, ai_sitemap): il peso del check cambiava a seconda dello status ritornato (es. 0.3 se missing, 1.2 se present). Conseguenza matematica: i check passati pesavano sproporzionatamente nel denominatore — il bug favoriva chi non aveva i segnali (li penalizzava meno). Pesi resi uniformi e proporzionati alla forza dello standard. - HTTP 4xx/5xx pre-check assente: un sito che rispondeva 403 (geoblock dell'IP del nostro audit) o 503 (manutenzione) veniva analizzato come se fosse contenuto pubblico — tutti i check segnavano "missing" attribuendo la colpa al dealer invece che al fetch fallito. Ora: early-return con error
http_error esplicito. - DNS fallback base recompute: quando un dominio aveva apex DNS non risolvente (es.
opportunitycar.it, solo www. risolveva), l'audit faceva fallback su www. per la homepage ma NON aggiornava la URL base usata per i sub-endpoint (/sitemap.xml, /llms.txt, ecc.). Tutti i check di asse ainative fallivano per DNS error — falso 1.64/10 invece di 8.89. Fix: ricalcolo base dalla URL effettiva post-fetch.
Trasparenze aggiunte (nuovo):
- Note difendibili per ogni check: il backend genera ora una nota in italiano per ogni risultato che spiega cosa significa il punteggio in modo specifico (no genericità tipo "OK") e con riferimento implicito alla spec normativa. Esposta nel
/verify response come campo note. - Spec_ref normativa per ogni check: ogni check ha ora un campo
spec_ref popolato dalla mappa SPEC_REFS che cita la fonte ufficiale (RFC, Google Search Central, schema.org, OWASP ASVS, llmstxt.org). Permette a chiunque di riprodurre il giudizio contro una fonte esterna. - UI "Dettagli per check": nuova sezione collassabile nel risultato AInvisible che mostra una tabella per asse con icona status, label, score×peso, nota difendibile, fonte normativa. Trasforma il punteggio da "scatola nera" a "auditable by anyone".
- Disclaimer onesti sul campione: il listing pubblico dichiara ora che i siti analizzati sono "audit eseguiti tramite questo strumento" (campione self-selected da chi clicca "Analizza"), NON un campione statisticamente rappresentativo del mercato dealer italiano. Il rank percentile usa
toFixed(2) per evitare il falso "top 0.0%" quando si sta in realtà nel top 0.02%. - Etichetta "SPERIMENTALE" più visibile sull'indicatore AI-Native con link diretto a llmstxt.org e warn box che ribadisce: "Nessuno di questi è uno standard W3C/IETF ratificato. La loro assenza non penalizza il voto complessivo."
Cache invalidation: query /verify ora richiede schema v2 (evidences->'machine.jsonld' ? 'note') per il cache-hit. Record pre-2026-05-14 vengono automaticamente ri-scansionati al prossimo verify.
Migration view audit_scans_latest: la VIEW che alimenta il listing pubblico /sites filtra solo scan con schema v2. I ~5000 record pre-fix restano nella tabella audit_scans come storico ma sono NASCOSTI dal listing pubblico finché lo script di rescan batch non li ripopola con il framework corrente. Side effect: subito dopo la migration il listing mostra pochi risultati e cresce gradualmente nelle 3-4 ore successive al ritmo del worker di rescan (30 audit/min).
Pesi indicatore AI-Native — rebalance: prima i pesi premiavano sproporzionatamente i segnali sperimentali (llms.txt = 2.0, robots_ai_ua = 1.5, ai-plugin = 1.2). DealerMAX serve di default esattamente quei segnali — il framework era strutturalmente biased a proprio favore. Nel rebalance i pesi sono proporzionati alla forza dello standard di riferimento (schema.org/RFC = peso pieno, llmstxt.org/spawning = ridotto, ChatGPT Plugins deprecato = minimo informativo).
Vehicle ItemList in JSON-LD home dealer (apimax): la home graph dealer DealerMAX ora include un nodo ItemList con i top 5 veicoli vetrina come @type: Vehicle con 10 campi schema.org (fuelType, mileageFromOdometer, vehicleModelDate, color, bodyType, vehicleTransmission, driveWheelConfiguration, enginePower, itemCondition, description) + Offer (price, priceCurrency=EUR, availability). Soddisfa il Tier 1 di machine.jsonld (Vehicle/Car presente) e i Google Vehicle Listings required fields.