Monitorare l'applicazione web con l'API di reporting

Utilizza l'API Reporting per monitorare violazioni della sicurezza, chiamate API ritirate e altro ancora.

Alcuni errori si verificano solo in produzione. Non li vedrai localmente o durante lo sviluppo perché utenti reali, reti reali e dispositivi reali cambiano il gioco. L'API Reporting aiuta a rilevare alcuni di questi errori, come violazioni della sicurezza o chiamate API ritirate e prossime al ritiro nel tuo sito, e li trasmette a un endpoint che hai specificato.

Ti consente di dichiarare ciò che vuoi monitorare utilizzando le intestazioni HTTP ed è gestita dal browser.

La configurazione dell'API Reporting ti dà la certezza che, quando gli utenti riscontrano questi tipi di errori, ne sarai al corrente e potrai correggerli.

Questo post illustra le funzionalità di questa API e come utilizzarla. Iniziamo.

Panoramica

Diagramma che riassume i passaggi riportati di seguito, dalla generazione del report all'accesso al report da parte dello sviluppatore
Come vengono generati e inviati i report.

Supponiamo che il tuo sito, site.example, abbia un Content-Security-Policy e un Document-Policy. Non sai a cosa servono? Non preoccuparti, sarai comunque in grado di comprendere questo esempio.

Decidi di monitorare il tuo sito per sapere quando queste policy vengono violate, ma anche perché vuoi tenere d'occhio le API ritirate o che verranno ritirate a breve che il tuo codebase potrebbe utilizzare.

Per farlo, configura un'intestazione Reporting-Endpoints e mappa i nomi di questi endpoint utilizzando la direttiva report-to nelle policy, se necessario.

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the `default` endpoint

Si verifica un evento imprevisto e queste norme vengono violate per alcuni dei tuoi utenti.

Esempi di violazioni

index.html

<script src="script.js"></script>
<!-- CSP VIOLATION: Try to load a script that's forbidden as per the Content-Security-Policy -->
<script src="https://example.com/script.js"></script>

script.js, caricato da index.html

// DOCUMENT-POLICY VIOLATION: Attempt to use document.write despite the document policy
try {
  document.write('<h1>hi</h1>');
} catch (e) {
  console.log(e);
}
// DEPRECATION: Call a deprecated API
const webkitStorageInfo = window.webkitStorageInfo;

Il browser genera un report sulle violazioni CSP, un report sulle violazioni delle norme relative ai documenti e un report sulle funzionalità ritirate che acquisiscono questi problemi.

Con un breve ritardo, fino a un minuto, il browser invia i report all'endpoint configurato per questo tipo di violazione. I report vengono inviati out-of-band dal browser stesso (non dal tuo server né dal tuo sito).

L'endpoint o gli endpoint ricevono questi report.

Ora puoi accedere ai report su questi endpoint e monitorare cosa è andato storto. Ora puoi iniziare a risolvere il problema che interessa i tuoi utenti.

Report di esempio

{
  "age": 2,
  "body": {
    "blockedURL": "https://site2.example/script.js",
    "disposition": "enforce",
    "documentURL": "https://site.example",
    "effectiveDirective": "script-src-elem",
    "originalPolicy": "script-src 'self'; object-src 'none'; report-to main-endpoint;",
    "referrer": "https://site.example",
    "sample": "",
    "statusCode": 200
  },
  "type": "csp-violation",
  "url": "https://site.example",
  "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}

Casi d'uso e tipi di report

L'API Reporting può essere configurata per aiutarti a monitorare molti tipi di avvisi o problemi interessanti che si verificano nel tuo sito:

Tipo di rapporto Esempio di una situazione in cui verrebbe generato un report
Violazione CSP (solo livello 3) Hai impostato un Content-Security-Policy (CSP) su una delle tue pagine, ma la pagina sta tentando di caricare uno script non consentito dal CSP.
Violazione COOP Hai impostato un Cross-Origin-Opener-Policy su una pagina, ma una finestra multiorigine sta tentando di interagire direttamente con il documento.
Violazione del COEP Hai impostato un Cross-Origin-Embedder-Policy su una pagina, ma il documento include un iframe multiorigine che non ha attivato il caricamento da parte di documenti multiorigine.
Violazione delle norme relative ai documenti La pagina ha un criterio del documento che impedisce l'utilizzo di document.write, ma uno script tenta di chiamare document.write.
Violazione delle norme relative alle autorizzazioni La pagina ha un criterio relativo alle autorizzazioni che impedisce l'utilizzo del microfono e uno script che richiede l'input audio.
Avviso di deprecazione La pagina utilizza un'API deprecata o che verrà deprecata; la chiama direttamente o utilizzando uno script di terze parti di primo livello.
Intervento La pagina sta tentando di fare qualcosa che il browser decide di non rispettare per motivi di sicurezza, prestazioni o esperienza utente. Esempio in Chrome: la pagina utilizza document.write su reti lente o chiama navigator.vibrate in un frame multiorigine con cui l'utente non ha ancora interagito.
Arresto anomalo Il browser si arresta in modo anomalo mentre il tuo sito è aperto.

Report

Il browser invia i report all'endpoint che hai configurato. Invia richieste con il seguente aspetto:

POST
Content-Type: application/reports+json

Il payload di queste richieste è un elenco di report.

Elenco di report di esempio

[
  {
    "age": 420,
    "body": {
      "columnNumber": 12,
      "disposition": "enforce",
      "lineNumber": 11,
      "message": "Document policy violation: document-write is not allowed in this document.",
      "policyId": "document-write",
      "sourceFile": "https://site.example/script.js"
    },
    "type": "document-policy-violation",
    "url": "https://site.example/",
    "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
  },
  {
    "age": 510,
    "body": {
      "blockedURL": "https://site.example/img.jpg",
      "destination": "image",
      "disposition": "enforce",
      "type": "corp"
    },
    "type": "coep",
    "url": "https://dummy.example/",
    "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
  }
]

Ecco i dati che puoi trovare in ciascuno di questi report:

Campo Descrizione
age Il numero di millisecondi tra il timestamp del report e l'ora corrente.
body I dati effettivi del report, serializzati in una stringa JSON. I campi contenuti nel body di un report sono determinati dal type del report. ⚠️ I report di tipi diversi hanno corpi diversi.
type Un tipo di report, ad esempio csp-violation o coep.
url L'indirizzo del documento o del lavoratore da cui è stato generato il report. I dati sensibili come nome utente, password e frammento vengono rimossi da questo URL.
user_agent L'intestazione User-Agent della richiesta da cui è stato generato il report.

Report con credenziali

Gli endpoint di reporting che hanno la stessa origine della pagina che genera il report ricevono le credenziali (cookie) nelle richieste che contengono i report.

Le credenziali possono fornire un contesto aggiuntivo utile sulla segnalazione, ad esempio se l'account di un determinato utente attiva costantemente errori o se una determinata sequenza di azioni eseguite su altre pagine attiva una segnalazione su questa pagina.

Quando e come il browser invia i report?

I report vengono inviati fuori banda dal tuo sito: il browser controlla quando vengono inviati agli endpoint configurati. Inoltre, non è possibile controllare quando il browser invia i report; li acquisisce, li mette in coda e li invia automaticamente in un momento opportuno.

Ciò significa che l'utilizzo dell'API Reporting non comporta problemi di rendimento.

I report vengono inviati con un ritardo fino a un minuto per aumentare le probabilità di inviarli in batch. In questo modo si risparmia larghezza di banda per rispettare la connessione di rete dell'utente, il che è particolarmente importante sui dispositivi mobili. Il browser può anche ritardare l'invio se è impegnato a elaborare un lavoro con priorità più elevata o se l'utente si trova su una rete lenta o congestionata in quel momento.

Problemi proprietari e di terze parti

I report generati a causa di violazioni o ritiri che si verificano nella tua pagina verranno inviati agli endpoint che hai configurato. Sono incluse le violazioni commesse da script di terze parti in esecuzione sulla tua pagina.

Le violazioni o le deprecazioni che si sono verificate in un iframe multiorigine incorporato nella tua pagina non verranno segnalate ai tuoi endpoint (almeno non per impostazione predefinita). Un iframe potrebbe configurare i propri report e persino inviarli al servizio di reporting del tuo sito, ovvero della prima parte, ma questo dipende dal sito con frame. Tieni presente che la maggior parte dei report viene generata solo se le norme di una pagina vengono violate e che le norme della tua pagina e quelle dell'iframe sono diverse.

Esempio con deprecazioni

Se l'intestazione Reporting-Endpoints è configurata sulla tua pagina: le chiamate API ritirate effettuate da script di terze parti in esecuzione sulla tua pagina verranno segnalate al tuo endpoint. La chiamata API deprecata da un iframe incorporato nella tua pagina non verrà segnalata al tuo endpoint. Un report di ritiro verrà generato solo se il server iframe ha configurato Reporting-Endpoints e verrà inviato all'endpoint configurato dal server iframe.
Se l'intestazione Reporting-Endpoints è configurata nella tua pagina: le chiamate API deprecate effettuate da script di terze parti in esecuzione nella tua pagina verranno segnalate al tuo endpoint. Le chiamate API ritirate chiamate da un iframe incorporato nella tua pagina non verranno segnalate al tuo endpoint. Un report di ritiro verrà generato solo se il server iframe ha configurato Reporting-Endpoints e verrà inviato all'endpoint configurato dal server iframe.

Supporto browser

La tabella seguente riassume il supporto del browser per l'API Reporting v1, ovvero con l'intestazione Reporting-Endpoints. Il supporto del browser per l'API Reporting v0 (intestazione Report-To) è lo stesso, ad eccezione di un tipo di report: Network Error Logging non è supportato nella nuova API Reporting. Per maggiori dettagli, leggi la guida alla migrazione.

Tipo di rapporto Chrome Chrome per iOS Safari Firefox Edge
Violazione CSP (solo livello 3)* ✔ Sì ✔ Sì ✔ Sì ✘ No ✔ Sì
Network Error Logging ✘ No ✘ No ✘ No ✘ No ✘ No
Violazione COOP/COEP ✔ Sì ✘ No ✔ Sì ✘ No ✔ Sì
Tutti gli altri tipi: violazione delle norme relative ai documenti, ritiro, intervento, arresto anomalo ✔ Sì ✘ No ✘ No ✘ No ✔ Sì

Questa tabella riassume solo il supporto per report-to con la nuova intestazione Reporting-Endpoints. Leggi i suggerimenti per la migrazione dei report CSP se vuoi eseguire la migrazione a Reporting-Endpoints.

Utilizzo dell'API Reporting

Decidi dove inviare i report

Sono disponibili due opzioni:

  • Invia i report a un servizio di raccolta dei report esistente.
  • Inviare i report a un raccoglitore di report che crei e gestisci in autonomia.

Opzione 1: utilizza un servizio di raccolta dei report esistente

Ecco alcuni esempi di servizi di raccolta dei report:

Se conosci altre soluzioni, apri un problema per comunicarcelo e aggiorneremo questo post.

Oltre ai prezzi, tieni presente i seguenti punti quando selezioni un raccoglitore di report: 🧐

  • Questo raccoglitore supporta tutti i tipi di report? Ad esempio, non tutte le soluzioni di endpoint di reporting supportano i report COOP/COEP.
  • Ti senti a tuo agio nel condividere gli URL della tua applicazione con un raccoglitore di report di terze parti? Anche se il browser rimuove le informazioni sensibili da questi URL, le informazioni sensibili potrebbero essere divulgate in questo modo. Se ti sembra troppo rischioso per la tua applicazione, gestisci il tuo endpoint di reporting.

Opzione 2: crea e gestisci il tuo raccoglitore di report

La creazione di un server che riceve i report non è così semplice. Per iniziare, puoi creare un fork del nostro boilerplate leggero. È creato con Express e può ricevere e visualizzare i report.

Quando crei il tuo raccoglitore di report:

  • Cerca le richieste POST con un Content-Type di application/reports+json per riconoscere le richieste di report inviate dal browser al tuo endpoint.
  • Se l'endpoint si trova su un'origine diversa da quella del tuo sito, assicurati che supporti le richieste preflight CORS.

Opzione 3: combina le opzioni 1 e 2

Potresti voler affidare a un fornitore specifico alcuni tipi di report, ma avere una soluzione interna per altri.

In questo caso, imposta più endpoint come segue:

Reporting-Endpoints: endpoint-1="https://reports-collector.example", endpoint-2="https://my-custom-endpoint.example"

Configurare l'intestazione Reporting-Endpoints

Imposta un'intestazione della risposta Reporting-Endpoints. Il valore deve essere una o una serie di coppie chiave-valore separate da virgole:

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

Se esegui la migrazione dalla precedente API Reporting alla nuova API Reporting, potrebbe essere utile impostare entrambi Reporting-Endpoints e Report-To. Per i dettagli, consulta la guida alla migrazione. In particolare, se utilizzi i report per le violazioni di Content-Security-Policy utilizzando solo la direttiva report-uri, controlla i passaggi di migrazione per i report CSP.

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Report-To: ...

Chiavi (nomi degli endpoint)

Ogni chiave può essere un nome a tua scelta, ad esempio main-endpoint o endpoint-1. Puoi decidere di impostare endpoint con nomi diversi per tipi di report diversi, ad esempio my-coop-endpoint, my-csp-endpoint. In questo modo, puoi indirizzare i report a endpoint diversi a seconda del tipo.

Se vuoi ricevere report su interventi, ritiri, arresti anomali o una combinazione di questi, imposta un endpoint denominato default.

Se l'intestazione Reporting-Endpoints non definisce alcun endpoint default, i report di questo tipo non verranno inviati (anche se verranno generati).

Valori (URL)

Ogni valore è un URL a tua scelta a cui verranno inviati i report. L'URL da impostare qui dipende da ciò che hai deciso nel passaggio 1.

Un URL endpoint:

Esempi

Reporting-Endpoints: my-coop-endpoint="https://reports.example/coop", my-csp-endpoint="https://reports.example/csp", default="https://reports.example/default"

Puoi quindi utilizzare ogni endpoint denominato nel criterio appropriato oppure utilizzare un unico endpoint in tutti i criteri.

Dove impostare l'intestazione?

Nella nuova API di reporting, quella trattata in questo post, i report hanno come ambito i documenti. Ciò significa che per una determinata origine, documenti diversi, come site.example/page1 e site.example/page2, possono inviare report a endpoint diversi.

Per ricevere report relativi a violazioni o ritiri che si verificano in qualsiasi pagina del tuo sito, imposta l'intestazione come middleware in tutte le risposte.

Ecco un esempio in Express:

const REPORTING_ENDPOINT_BASE = 'https://report.example';
const REPORTING_ENDPOINT_MAIN = `${REPORTING_ENDPOINT_BASE}/main`;
const REPORTING_ENDPOINT_DEFAULT = `${REPORTING_ENDPOINT_BASE}/default`;

app.use(function (request, response, next) {
  // Set up the Reporting API
  response.set(
    'Reporting-Endpoints',
    `main-endpoint="${REPORTING_ENDPOINT_MAIN}", default="${REPORTING_ENDPOINT_DEFAULT}"`,
  );
  next();
});

Modifica le policy

Ora che l'intestazione Reporting-Endpoints è configurata, aggiungi una direttiva report-to a ogni intestazione delle norme per cui vuoi ricevere report sulle violazioni. Il valore di report-to deve essere uno degli endpoint denominati che hai configurato.

Puoi utilizzare più endpoint per più policy o utilizzare endpoint diversi per le varie policy.

Per ogni policy, il valore di report-to deve essere uno degli endpoint denominati che hai configurato.

report-to non è necessario per i report di ritiro, intervento e arresto anomalo. Questi report non sono associati ad alcuna policy. Vengono generati a condizione che sia configurato un endpoint default e vengono inviati a questo endpoint default.

Esempio

# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0;report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the default endpoint

Esegui il debug della configurazione dei report

Generare report intenzionalmente

Quando configuri l'API Reporting, è probabile che tu debba violare intenzionalmente le tue policy per verificare se i report vengono generati e inviati come previsto.

Risparmia tempo

I report potrebbero essere inviati con un ritardo di circa un minuto, che è un periodo di tempo lungo durante il debug. 😴 Fortunatamente, durante il debug in Chrome, puoi utilizzare il flag --short-reporting-delay per ricevere i report non appena vengono generati.

Esegui questo comando nel terminale per attivare questo flag:

YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay

Utilizzare DevTools

In Chrome, utilizza DevTools per visualizzare i report che sono stati inviati o che verranno inviati.

A partire da ottobre 2021, questa funzionalità è sperimentale. Per utilizzarla, segui questi passaggi:

  1. Utilizza Chrome versione 96 e successive (controlla digitando chrome://version nel browser)
  2. Digita o incolla chrome://flags/#enable-experimental-web-platform-features nella barra degli indirizzi di Chrome.
  3. Fai clic su Attivata.
  4. Riavvia il browser.
  5. Apri Chrome DevTools.
  6. In Chrome DevTools, apri Impostazioni. In Esperimenti, fai clic su Attiva il riquadro API di reporting nel riquadro Applicazione.
  7. Ricarica DevTools.
  8. Ricarica la pagina. I report generati dalla pagina in cui è aperto DevTools verranno elencati nel riquadro Applicazione di Chrome DevTools, in API Reporting.
Chrome DevTools che elenca i report.
Chrome DevTools mostra i report generati sulla tua pagina e il relativo stato.

Stato del report

La colonna Stato indica se un report è stato inviato correttamente.

Stato Descrizione
Success Il browser ha inviato il report e l'endpoint ha risposto con un codice di esito positivo (200 o un altro codice di risposta di esito positivo 2xx).
Pending Il browser sta tentando di inviare il report.
Queued Il report è stato generato e il browser non sta tentando di inviarlo. Un report viene visualizzato come Queued in uno di questi due casi:
  • Il report è nuovo e il browser è in attesa di vedere se arrivano altri report prima di provare a inviarlo.
  • Il report non è nuovo; il browser ha già tentato di inviarlo, ma non è riuscito e sta aspettando prima di riprovare.
MarkedForRemoval Dopo aver riprovato per un po' (Queued), il browser ha smesso di tentare di inviare il report e lo rimuoverà presto dall'elenco dei report da inviare.

I report vengono rimossi dopo un po' di tempo, indipendentemente dal fatto che siano stati inviati correttamente o meno.

Risoluzione dei problemi

I report non vengono generati o non vengono inviati come previsto al tuo endpoint? Ecco alcuni suggerimenti per risolvere il problema.

I report non vengono generati

I report visualizzati in DevTools sono stati generati correttamente. Se il report che ti aspetti non viene visualizzato in questo elenco:

  • Controlla report-to nelle tue norme. Se la configurazione non è corretta, il report non verrà generato. Vai a Modifica le tue norme per risolvere il problema. Un altro modo per risolvere i problemi è controllare la console DevTools in Chrome: se nella console viene visualizzato un errore per la violazione prevista, significa che la policy è probabilmente configurata correttamente.
  • Tieni presente che in questo elenco verranno visualizzati solo i report generati per il documento in cui è aperto DevTools. Ad esempio, se il tuo sito site1.example incorpora un iframe site2.example che viola una norma e quindi genera un report, questo report verrà visualizzato in DevTools solo se apri l'iframe nella relativa finestra e apri DevTools per quella finestra.

I report vengono generati, ma non inviati o non ricevuti

Cosa succede se riesci a visualizzare un report in DevTools, ma l'endpoint non lo riceve?

  • Assicurati di utilizzare ritardi brevi. Forse il motivo per cui non riesci a visualizzare un report è perché non è ancora stato inviato.
  • Controlla la configurazione dell'intestazione Reporting-Endpoints. Se si verifica un problema, un report generato correttamente non verrà inviato. In questo caso, in DevTools lo stato del report rimarrà Queued (potrebbe passare a Pending e poi tornare rapidamente a Queued quando viene effettuato un tentativo di invio). Alcuni errori comuni che potrebbero causare questo problema:

  • L'endpoint viene utilizzato, ma non è configurato. Esempio:

Codice con un errore
 Document-Policy: document-write=?0;report-to=endpoint-1;
 Reporting-Endpoints: default="https://reports.example/default"

I report sulle violazioni di Document-Policy devono essere inviati a endpoint-1, ma questo nome di endpoint non è configurato in Reporting-Endpoints.

  • Manca l'endpoint default. Alcuni tipi di report, come quelli relativi a ritiro e intervento, verranno inviati solo all'endpoint denominato default. Scopri di più in Configurare l'intestazione Reporting-Endpoints.

  • Controlla la presenza di problemi nella sintassi delle intestazioni delle norme, ad esempio virgolette mancanti. Visualizza i dettagli.

  • Verifica che l'endpoint possa gestire le richieste in entrata.

    • Assicurati che l'endpoint supporti le richieste preflight CORS. In caso contrario, non può ricevere report.

    • Testa il comportamento dell'endpoint. Per farlo, anziché generare i report manualmente, puoi emulare il browser inviando al tuo endpoint richieste che sembrano quelle che invierebbe il browser. Esegui questo comando:

    curl --header "Content-Type: application/reports+json" \
      --request POST \
      --data '[{"age":420,"body":{"columnNumber":12,"disposition":"enforce","lineNumber":11,"message":"Document policy violation: document-write is not allowed in this document.","policyId":"document-write","sourceFile":"https://dummy.example/script.js"},"type":"document-policy-violation","url":"https://dummy.example/","user_agent":"xxx"},{"age":510,"body":{"blockedURL":"https://dummy.example/img.jpg","destination":"image","disposition":"enforce","type":"corp"},"type":"coep","url":"https://dummy.example/","user_agent":"xxx"}]' \
      YOUR_ENDPOINT
    

    L'endpoint deve rispondere con un codice di esito positivo (200 o un altro codice di risposta di esito positivo 2xx). In caso contrario, si è verificato un problema con la sua configurazione.

Solo report

Le intestazioni dei criteri -Report-Only e Reporting-Endpoints interagiscono tra di loro.

Gli endpoint configurati in Reporting-Endpoints e specificati nel campo report-to di Content-Security-Policy, Cross-Origin-Embedder-Policy e Cross-Origin-Opener-Policy, riceveranno report quando queste policy vengono violate.

Gli endpoint configurati in Reporting-Endpoints possono essere specificati anche nel campo report-to di Content-Security-Policy-Report-Only, Cross-Origin-Embedder-Policy-Report-Only e Cross-Origin-Opener-Policy-Report-Only. Riceveranno anche report quando queste norme vengono violate.

Sebbene i report vengano inviati in entrambi i casi, le intestazioni -Report-Only non applicano i criteri: non si verificheranno interruzioni o blocchi, ma riceverai report su ciò che si sarebbe interrotto o bloccato.

ReportingObserver

L'API JavaScript ReportingObserver può aiutarti a osservare gli avvisi lato client.

ReportingObserver e l'intestazione Reporting-Endpoints generano report che sembrano uguali, ma consentono casi d'uso leggermente diversi.

Usa ReportingObserver se:

  • Vuoi monitorare solo i ritiri o gli interventi del browser. ReportingObserver mostra avvisi lato client come ritiri e interventi del browser, ma a differenza di Reporting-Endpoints, non acquisisce altri tipi di report, come violazioni di CSP o COOP/COEP.
  • Devi reagire a queste violazioni in tempo reale. ReportingObserver consente di collegare un callback a un evento di violazione.
  • Vuoi allegare ulteriori informazioni a un report per facilitare il debug, utilizzando il callback personalizzato.

Un'altra differenza è che ReportingObserver viene configurato solo lato client: puoi utilizzarlo anche se non hai il controllo delle intestazioni lato server e non puoi impostare Reporting-Endpoints.

Per approfondire

Un ringraziamento speciale a Ian Clelland, Eiji Kitamura e Milica Mihajlija per le loro revisioni e i loro suggerimenti su questo documento.