> For the complete documentation index, see [llms.txt](https://docs.opencityitalia.it/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opencityitalia.it/sviluppatori-e-partner-tecnologici/integrazioni/integrazione-con-protocollo-informatico/protocol-proxy-specifiche-implementative.md).

# Protocol Proxy: Specifiche Implementative

## Requisiti Generali - controllare pagina standard e convenzioni

* Ogni microservizio deve rispettare gli [standard della piattaforma](https://docs.opencityitalia.it/v/developers/standard-e-convenzioni/standard-della-piattaforma)
* Ogni proxy deve soddisfare i requisiti suggeriti dal [12 factors manifest](https://12factor.net/it/)
* Esposizione di un endpoint`/status` per l'healthcheck: esso deve essere restituire 200 se il sistema è "healthy" e 503 in caso si presentino un problemi di connessione con kafka
* Esposizione delle metriche mediante l'endpoint `/metrics` con Prometheus utilizzando [la convenzione da loro suggerita](https://prometheus.io/docs/practices/naming/)
* Terminazione pulita del servizio (timeout di 15 secondi)
* Esposizione di un endpoint `/docs` per la consultazione della documentazione delle API esposte dal servizio secondo lo standard OpenAPI
* Integrazione con [Sentry](https://https/.sentry.io) per l'error reporting
* Il sistema di logging deve rispettare il formato Apache e descrivere nei tre livelli debug, error e info. Ogni log, quando possibile, deve loggare il `remote_id` e l'`id` del documento processato
* Il README deve seguire le [linee guida della pubblicazione del software open source](https://docs.italia.it/italia/developers-italia/lg-acquisizione-e-riuso-software-per-pa-docs/it/stabile/attachments/allegato-a-guida-alla-pubblicazione-open-source-di-software-realizzato-per-la-pa.html#file-readme)
* il nome del progetto e del servizio devono essere nella seguente forma : "Protocol Proxy \<Nome del Protocollo Specifico>"
* Inserire il file `.gitlab-ci.yml` riportando in esso [questa](https://docs.opencityitalia.it/installazione-e-manutenzione/integrazioni/protocolli) pipeline

## Metriche in dettaglio

Il Protocol Proxy deve esporre le seguenti metriche:

<table><thead><tr><th width="258">Metrica</th><th>Labels</th><th>Descrizione</th></tr></thead><tbody><tr><td><code>oc_document_validation_errors_total</code></td><td>cluster, env, app_name</td><td>la metrica deve misurare gli errori di validazione sull'evento letto (es. il <code>transmission_type</code> contiene un valore diverso da <code>Inbound</code> o <code>Outbound</code>)</td></tr><tr><td><code>oc_api_requests_total</code></td><td>cluster, env, method, app_name, status_code</td><td>la metrica deve monitorare le chiamate http indicandone lo status code</td></tr><tr><td><code>oc_document_success_events_total</code></td><td>cluster, env, app_name</td><td>la metrica deve misurare solo gli eventi per cui il proxy ha una configurazione e che sono stati processati con successo</td></tr><tr><td><code>oc_document_failed_events_total</code></td><td>cluster, env, app_name</td><td>la metrica deve misurare gli eventi validi di cui però è fallito il processing per qualsiasi motivo (escluso il caso in cui non esiste una configurazione per esso)</td></tr><tr><td><code>oc_document_provider_errors_total</code></td><td>cluster, env, app_name</td><td>la metrica deve misurare gli eventi validi di cui però è fallito il processing a causa di un errore sul provider</td></tr><tr><td><code>oc_document_internal_errors_total</code></td><td>cluster, env, app_name</td><td>la metrica deve misurare gli eventi validi di cui però è fallito il processing per errori interni al codice</td></tr><tr><td><code>oc_document_provider_latency_bucket</code></td><td>cluster, env, app_name</td><td>istogramma che mostra la distribuzione di latenza delle risposte del provider</td></tr></tbody></table>

## Requisiti normativi

* Avere una specifica in formato OpenAPI v3
* Rispettare la [Linee Guida di interoperabilità](https://docs.italia.it/italia/piano-triennale-ict/lg-modellointeroperabilita-docs): in particolare per quanto riguarda
  * [il formato dei dati](https://docs.italia.it/italia/piano-triennale-ict/lg-modellointeroperabilita-docs/it/bozza/doc/04_Raccomandazioni%20di%20implementazione/04_raccomandazioni-tecniche-generali/02_formato-dei-dati.html) (4.2)
  * [raccomandazioni sul naming](https://docs.italia.it/italia/piano-triennale-ict/lg-modellointeroperabilita-docs/it/bozza/doc/04_Raccomandazioni%20di%20implementazione/04_raccomandazioni-tecniche-generali/03_progettazione-e-naming.html) (4.3) optando per la scelta di `snake_case` per i nomi degli attributi
  * logging (4.4)
  * risultare valido nel [validatore ufficiale OA3](https://github.com/italia/api-oas-checker)

## Documentazione API di Esempio - Swagger

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/metrics" method="get" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/status" method="get" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/schema" method="get" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/tenants/" method="post" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/tenants/{id}" method="get" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/tenants/{id}" method="put" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/tenants/{id}" method="delete" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/services/" method="post" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/services/{id}" method="get" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/services/{id}" method="put" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>" path="/services/{id}" method="delete" %}
<https://api.qa.stanzadelcittadino.it/registry-proxy/agspr/v1/openapi.json>
{% endopenapi %}

## Specifiche funzionali

* Il servizio deve essere multi tentant e multi servizio: deve quindi essere in grado di gestire le confiugurazioni per più tenant a cui possono essere attribuiti più servizi con il corrente sistema di protocollazione.
* Ogni richiesta sia essa appartenente alla fase 1 o alla fase 2 descritte nella sezione "[workflow sistema di protocollazione](/sviluppatori-e-partner-tecnologici/integrazioni/integrazioni-con-il-flusso-delle-pratiche/webhooks.md)" devono essere trattate in maniera atomica.
* Lo storage deve essere compatibile con Aws s3, Azure e local file system.

## Configurazione del microservizio (variabili d'ambiente)

Il servizio deve essere configurabile attraverso le seguenti variabili d'ambiente.

Se le varibili senza valore di default non vengono settate, il servizio deve notificare la mancata impostazione attraverso un log di livello error e terminare in maniera pulita la propria esecuzione.

<table><thead><tr><th width="348.3333333333333">Nome</th><th>Default</th><th>Descrizione</th></tr></thead><tbody><tr><td><code>ENVIRONMENT</code></td><td>local</td><td>Indica l'ambiente di sviluppo (locale, dev, prod, ecc.) utilizzato da Sentry.</td></tr><tr><td><code>DEBUG</code></td><td>true</td><td>...</td></tr><tr><td><code>SENTRY_ENABLED</code></td><td>false</td><td>...</td></tr><tr><td><code>SENTRY_DSN</code></td><td>nessun valore</td><td>Endpoint per il monitoraggio di Sentry.</td></tr><tr><td><code>KAFKA_SERVER</code></td><td>kafka:9092</td><td>Lista di lunghezza variabile i cui elementi devono essere separati da virgola.<br>lista degli Indirizzi dei broker Kafka per connettersi al cluster.</td></tr><tr><td><code>KAFKA_CONSUMER_GROUP</code></td><td>&#x3C;nome_del_servizio></td><td>Consumer group per Kafka.</td></tr><tr><td><code>KAFKA_CONSUMER_TOPIC</code></td><td>documents</td><td>Identifica il topic da cui consumare gli eventi Kafka.</td></tr><tr><td><code>KAFKA_PRODUCER_TOPIC</code></td><td>documents</td><td>Identifica il topic a cui inviare gli eventi Kafka.</td></tr><tr><td><code>KAFKA_RETRY_TOPIC</code></td><td>nessun valore</td><td>topic in cui produrre gli eventi consumati dal meccanismo di retry</td></tr><tr><td><code>SERVER_ADDRESS_PORT</code></td><td>0.0.0.0:8080</td><td>Indica l'indirizzo e la porta utilizzati per l'healthcheck.</td></tr><tr><td><code>CACHE_EXPIRATION</code></td><td>5m</td><td>...</td></tr><tr><td><code>CACHE_EVICTION</code></td><td>10m</td><td>...</td></tr><tr><td><code>STORAGE_TYPE</code></td><td>local</td><td>Tipo di storage dei pagamenti: s3, azure, local</td></tr><tr><td><code>STORAGE_ENDPOINT</code></td><td>nessun valore</td><td>Indirizzo di accesso allo storage.</td></tr><tr><td><code>STORAGE_ACCESS_S3_KEY</code></td><td>nessun valore</td><td>Chiave di accesso allo storage.</td></tr><tr><td><code>STORAGE_KEY_S3_ACCESS_SECRET</code></td><td>nessun valore</td><td>Chiave segreta di accesso allo storage.</td></tr><tr><td><code>STORAGE_S3_REGION</code></td><td>nessun valore</td><td>Location del cloud storage</td></tr><tr><td><code>STORAGE_BUCKET</code></td><td>nessun valore</td><td>Nome dello storage</td></tr><tr><td><code>STORAGE_BASE_PATH</code></td><td>"/data/"</td><td>Basepath dello storage</td></tr><tr><td><code>STORAGE_AZURE_ACCOUNT</code></td><td>nessun valore</td><td>Chiave dello storage AZURE</td></tr><tr><td><code>STORAGE_AZURE_KEY</code></td><td>nessun valore</td><td>Password dello storage AZURE</td></tr><tr><td><code>STORAGE_LOCAL_PATH</code></td><td>/data/</td><td></td></tr><tr><td><code>SDC_AUTH_TOKEN_USER</code></td><td>nessun valore</td><td>utente autenticazione per recuperare il token dalla piattaforma</td></tr><tr><td><code>SDC_AUTH_TOKEN_PASSWORD</code></td><td>nessun valore</td><td>password autenticazione per recuperare il token dalla piattaforma</td></tr></tbody></table>

## Test

### Protocol Proxy Tests Checklist

Se si sta facendo il deploy di un **nuovo** microservizio per la prima volta o si sta aggiungendo una nuova API o una nuova pagina a una interfaccia esistente, è necessario aggiungere alcuni controlli di qualità minima prima del rilascio.

### Controlli <a href="#user-content-controlli" id="user-content-controlli"></a>

* Test automatici delle API nella CI (usare [hurl](https://hurl.dev/), [qui](https://docs.opencityitalia.it/installazione-e-manutenzione/integrazioni/protocolli) un esempio di utilizzo e [qui](https://docs.opencityitalia.it/installazione-e-manutenzione/integrazioni/protocolli) un esempio di integrazione nelle CI)
* Test flusso standard
  * Inserire la configurazione del tenant
  * Inserire la configurazione del servizio
  * Inserire un esempio di documento non protocollato nel topic documents e verificare che venga correttamente protocollato
  * Inserire un esempio di documento protocollato nel topic documents e verificare che venga ignorato
  * Inserire un esempio di documento non protocollato nel topic documents per cui non esiste una configurazione di tenant e/o di servizio e verificare che venga ignorato
* Test flusso di errore
  * Modificare la configurazione del servizio in modo che sia errata (mettendo ad esempio credenziali errate)
  * Inserire un esempio di documento non protocollato nel topic documents e verificare che, a seguito del fallimento, venga prodotto un evento nel topic di retry
  * Correggere la configurazione del servizio
  * Inserire il documento prodotto nel topic di retry all'interno del topic documents e verificare che venga correttamente protocollato


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.opencityitalia.it/sviluppatori-e-partner-tecnologici/integrazioni/integrazione-con-protocollo-informatico/protocol-proxy-specifiche-implementative.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
