Source: https://eleccp.com/it/formato-archivio
Language: it

Dati e trasparenza

# Formato archivio

Come leggere, conservare e trasferire i dati della tua organizzazione, anche senza EleCCP.

[Termini: esportazione e passaggio](https://eleccp.com/it/termini#cessazione-pacchetto-dati-e-passaggio-ad-altro-servizio)

## Portabilità e Data Act

Questa pagina raccoglie le informazioni tecniche sul formato di esportazione per la portabilità dei dati e il passaggio ad altro fornitore o a un’infrastruttura propria, ai sensi del capo VI del  [Regolamento (UE) 2023/2854 (Data Act)](https://eur-lex.europa.eu/eli/reg/2023/2854/oj/ita) , in particolare dell’articolo 26. Descrive strutture, campi, relazioni e limiti del formato; le modalità di richiesta, i tempi e le condizioni del servizio sono nell’articolo 15 dei Termini.

La sezione  [Dati non compresi nell’archivio](https://eleccp.com/it/formato-archivio#dati-non-compresi-nell-archivio)  elenca le esclusioni e il motivo di ciascuna. Quelle relative al funzionamento interno ai sensi dell’articolo 25, paragrafo 2, lettera f), riguardano il rischio di violazione dei segreti commerciali del Fornitore e non possono ostacolare o ritardare il passaggio. Restano esportabili i dati del cliente e i metadati necessari a interpretarli e riutilizzarli.

Le impronte SHA-256 servono a verificare l’integrità dei file: non sono firme digitali né certificazioni di autenticità.

**Versione del formato: 6** — in vigore dal 28 settembre 2026. Identificativo: `safe-haccp-archivio-organizzazione`. Indirizzo di questa pagina:  [https://eleccp.com/it/formato-archivio](https://eleccp.com/it/formato-archivio) .

EleCCP consegna all'organizzazione, quando lo chiede o quando chiude, una copia completa dei suoi dati: i registri di autocontrollo, la tracciabilità, i richiami, lo storico delle correzioni e tutti i file originali (foto, documenti, note vocali). Questa pagina descrive com'è fatta quella copia, in modo che si possa leggere e conservare anche senza EleCCP.

## Com'è fatto l'archivio

L'archivio è diviso in **pacchetti ZIP**, ognuno apribile da solo. Un pacchetto non supera la dimensione indicata in `manifest.json` (`package_size_limit_bytes`); un file più grande di quel limite sta da solo nel suo pacchetto.

```
pacchetto 1                        i dati: si apre per primo
  LEGGIMI.txt                      come leggere l'archivio, in italiano
  manifest.json                    l'indice di tutto l'archivio
  organizzazione.json              chi è l'organizzazione: azienda, organizzazione, membri
  dati/<tipo>.jsonl                un file per tipo di dato, un record per riga
pacchetti 2, 3, …                  i file originali
  manifest-parte.json              i file di quel pacchetto, con l'impronta
  file/<media_id>-<nome>           i file originali
```

I pacchetti si chiamano `archivio-<organizzazione>-<export_id>-pacchetto-<NNN>.zip`, con il numero a tre cifre. Per verificare di averli tutti e integri si confronta l'impronta SHA-256 di ogni file ZIP con quella elencata in `manifest.json` (`packages[].sha256`); l'impronta del pacchetto 1, che non può stare dentro sé stesso, è riportata nell'email di consegna e in EleCCP.

## Regole generali

- **Codifica**: tutti i file di testo sono UTF-8.

- **`dati/<tipo>.jsonl`**: [JSON Lines](https://jsonlines.org/) — un oggetto JSON per riga, un record per oggetto. Un tipo senza record ha il file vuoto.

- **Date e ore** (tipo *data e ora*): ISO 8601 con il fuso, in UTC (es. `2026-09-28T08:15:00+00:00`). Per l'ora locale si usa il fuso della sede (`site.timezone`).

- **Date** (tipo *data*): `AAAA-MM-GG`, nel calendario della sede.

- **Numeri decimali** (es. le quantità) sono scritti come testo (`"1.500"`), per non perdere cifre.

- **Identificativi**: ogni record ha un identificativo pubblico (`id`, o `external_id`), un UUID. Un campo che cita un altro record ne porta l'identificativo: la colonna *Rimanda a* dice in quale tipo cercarlo. Le persone sono citate con il loro numero (`*_user_id`), che si ritrova in `organizzazione.json` → `members`.

- **null e vuoto**: `null` vuol dire che il dato non c'è (non registrato, o non applicabile); una stringa vuota vuol dire che il campo esiste ma non è stato compilato.

- **Correzioni**: il record nel file del suo tipo è la versione attuale; ogni versione precedente a una correzione è in `dati/record_version.jsonl`, con il motivo e l'autore.

- **Campi in più**: chi legge l'archivio deve ignorare i campi che non conosce. Un campo nuovo fa comunque salire la versione del formato (vedi in fondo).

## `LEGGIMI.txt`

Un testo in italiano che spiega che cos'è l'archivio, da quanti pacchetti è composto, com'è fatto, come si seguono le relazioni fra i record, quanti record ha ogni tipo, quanti file sono stati copiati e che cosa manca. Rimanda a questa pagina. Non contiene dati che non siano anche negli altri file.

## `manifest.json` (pacchetto 1)

L'indice di tutto l'archivio.

| Campo | Tipo | Significato |
| --- | --- | --- |
| `format` | testo | Sempre `safe-haccp-archivio-organizzazione`: dice che il file è un manifest di questo formato |
| `format_version` | intero | La versione del formato con cui l'archivio è stato scritto |
| `format_url` | testo | L'indirizzo di questa pagina |
| `export_id` | uuid | Identificativo dell'archivio: è lo stesso in tutti i pacchetti |
| `organization_id` | intero | Numero dell'organizzazione |
| `organization_name` | testo o null | Nome dell'organizzazione |
| `snapshot_at` | data e ora | Il momento in cui i dati sono stati letti |
| `extracted_at` | data e ora | Uguale a `snapshot_at` (mantenuto per compatibilità) |
| `recovery_until` | data e ora o null | Se l'organizzazione è in chiusura: fino a quando i dati restano recuperabili in EleCCP |
| `package_size_limit_bytes` | intero | La dimensione massima di un pacchetto, in byte |
| `package_count` | intero | Quanti pacchetti compongono l'archivio, questo compreso |
| `files_count` | intero | Quanti file originali sono stati copiati |
| `kinds` | lista | I tipi di dato, uno per file `dati/<tipo>.jsonl` (vedi sotto) |
| `packages` | lista | Tutti i pacchetti, dal primo (vedi sotto) |
| `missing` | lista | Ciò che manca: file non copiati e parti di `organizzazione.json` (vedi sotto) |

Ogni elemento di `kinds`:

| Campo | Tipo | Significato |
| --- | --- | --- |
| `kind` | testo | Il tipo di dato |
| `count` | intero | Quanti record contiene |
| `path` | testo | Il file nel pacchetto 1 (`dati/<tipo>.jsonl`) |

Ogni elemento di `packages`:

| Campo | Tipo | Significato |
| --- | --- | --- |
| `index` | intero | Numero del pacchetto: 1 per i dati, da 2 in poi per i file |
| `filename` | testo | Nome del file ZIP |
| `size_bytes` | intero o null | Dimensione in byte (null per il pacchetto 1: un file non può contenere la propria dimensione) |
| `sha256` | testo o null | Impronta SHA-256 del file ZIP (null per il pacchetto 1, per la stessa ragione: la sua impronta è nell'email e in EleCCP) |
| `contents` | testo | Solo per il pacchetto 1: che cosa contiene |
| `files_count` | intero | Quanti file originali contiene |
| `files` | lista | I file originali che contiene (vedi sotto) |

Ogni elemento di `files` (qui e in `manifest-parte.json`):

| Campo | Tipo | Significato |
| --- | --- | --- |
| `media_id` | uuid | Identificativo del file, lo stesso citato dai dati (`attachments`, tipo `file`) |
| `path` | testo | Dove si trova nel pacchetto: `file/<media_id>-<nome>` |
| `original_filename` | testo | Il nome con cui il file è stato caricato |
| `content_type` | testo | Il tipo del file (es. `image/jpeg`, `application/pdf`) |
| `size_bytes` | intero | Dimensione in byte |
| `sha256` | testo | Impronta SHA-256 calcolata sui byte copiati nell'archivio |
| `declared_sha256` | testo o null | Impronta dichiarata da chi ha caricato il file, se c'era (non verificata) |

Ogni elemento di `missing` è di uno di due tipi. Un **file non copiato** (ha `media_id`):

| Campo | Tipo | Significato |
| --- | --- | --- |
| `media_id` | uuid | Il file che non è stato copiato |
| `reason` | testo | Perché (vedi i motivi) |
| `attempts` | intero | Quanti tentativi sono stati fatti |
| `expired_at` | data e ora o null | Solo con il motivo `expired`: quando il file è stato cancellato (null se la data non è stata letta) |

| Motivo | Significato |
| --- | --- |
| `not_found` | il file non esiste più nell'archivio dei file |
| `other_organization` | il file appartiene a un'altra organizzazione e non entra in questo archivio |
| `not_ready` | il caricamento del file non era mai stato completato |
| `media_unavailable` | l'archivio dei file non ha risposto, anche dopo i tentativi |
| `no_download_url` | l'archivio dei file non ha dato un modo per scaricarlo |
| `download_failed` | lo scaricamento non è riuscito, anche dopo i tentativi |
| `expired` | il file è stato cancellato perché la sua conservazione era finita (i mesi del vostro abbonamento dalla chiusura del record a cui era allegato); il record resta nei dati |

Una **parte di `organizzazione.json` non disponibile** (ha `section`):

| Campo | Tipo | Significato |
| --- | --- | --- |
| `file` | testo | Sempre `organizzazione.json` |
| `section` | testo | La parte che manca: `company`, `organization` o `members` |
| `source` | testo | Il servizio che doveva darla: `company`, `auth` o `haccp` |
| `reason` | testo | Perché (vedi i motivi) |

| Motivo | Significato |
| --- | --- |
| `service_unavailable` | il servizio non ha risposto |
| `service_error` | il servizio ha risposto con un errore |
| `not_found` | il servizio non conosce l'organizzazione (es. i dati dell'azienda non sono mai stati compilati) |
| `malformed_response` | il servizio ha risposto in una forma non leggibile |
| `haccp_unavailable` | il servizio che raccoglie queste informazioni non ha risposto |
| `haccp_error` | il servizio che raccoglie queste informazioni ha risposto con un errore |
| `not_supported` | la versione del servizio non sapeva ancora fornire queste informazioni |

Un file che manca non rende l'archivio incompleto negli altri contenuti: tutto ciò che è stato possibile copiare c'è, e ciò che manca è dichiarato qui.

## `manifest-parte.json` (pacchetti 2, 3, …)

Ogni pacchetto di file ha il suo indice, così si può verificare anche da solo.

| Campo | Tipo | Significato |
| --- | --- | --- |
| `format` | testo | Sempre `safe-haccp-archivio-organizzazione` |
| `format_version` | intero | La versione del formato |
| `format_url` | testo | L'indirizzo di questa pagina |
| `export_id` | uuid | Identificativo dell'archivio, lo stesso del pacchetto 1 |
| `organization_id` | intero | Numero dell'organizzazione |
| `package_index` | intero | Il numero di questo pacchetto |
| `root_manifest` | testo | Dove si trova l'indice completo (`manifest.json` nel pacchetto 1) |
| `files` | lista | I file di questo pacchetto, con la stessa forma di `files` in `manifest.json` |

## `organizzazione.json` (pacchetto 1)

Chi è l'organizzazione: i dati dell'azienda, l'organizzazione in EleCCP e i suoi membri. Non contiene password, codici di accesso, dispositivi, chiavi né coordinate bancarie o dati di pagamento.

| Campo | Tipo | Significato |
| --- | --- | --- |
| `format` | testo | Sempre `safe-haccp-archivio-organizzazione` |
| `format_version` | intero | La versione del formato |
| `format_url` | testo | L'indirizzo di questa pagina |
| `organization_id` | intero | Numero dell'organizzazione |
| `extracted_at` | data e ora | Quando queste informazioni sono state lette |
| `company` | oggetto o null | I dati dell'azienda (vedi sotto); null se non disponibili |
| `organization` | oggetto o null | L'organizzazione in EleCCP (vedi sotto); null se non disponibile |
| `members` | lista o null | Tutti i membri, anche usciti (vedi sotto); null se non disponibili |
| `missing` | lista | Le parti non disponibili: `{section, source, reason}`, con i motivi elencati sopra |

`company` — i dati dell'azienda:

| Campo | Tipo | Significato |
| --- | --- | --- |
| `organization_id` | intero | Numero dell'organizzazione |
| `legal_name` | testo | Ragione sociale |
| `trade_name` | testo | Insegna o nome commerciale |
| `vat_number` | testo | Partita IVA |
| `tax_code` | testo | Codice fiscale |
| `legal_address` | oggetto | Sede legale (indirizzo, vedi sotto) |
| `email` | testo | Email aziendale |
| `phone` | testo | Telefono |
| `website` | testo | Sito web |
| `is_active` | booleano | Falso se l'anagrafica è disattivata |
| `created_at` | data e ora | Quando l'anagrafica è stata creata |
| `deleted_at` | data e ora o null | Quando l'anagrafica è stata cancellata (null = no) |
| `billing_profile` | oggetto o null | Il profilo di fatturazione in uso (vedi sotto); null se non compilato |

`legal_address` e `billing_profile.address`:

| Campo | Tipo | Significato |
| --- | --- | --- |
| `address_line1` | testo | Indirizzo |
| `address_line2` | testo | Seconda riga dell'indirizzo |
| `city` | testo | Città |
| `state_province` | testo | Provincia |
| `postal_code` | testo | CAP |
| `country_code` | testo | Paese (codice ISO 3166-1 di due lettere, es. `IT`) |

`billing_profile`:

| Campo | Tipo | Significato |
| --- | --- | --- |
| `label` | testo | Nome del profilo |
| `legal_name` | testo | Intestatario delle fatture |
| `vat_number` | testo | Partita IVA |
| `tax_code` | testo | Codice fiscale |
| `address` | oggetto | Indirizzo di fatturazione (stessa forma della sede legale) |
| `billing_email` | testo | Email per le fatture |
| `pec_email` | testo | PEC |
| `sdi_code` | testo | Codice destinatario per la fatturazione elettronica |

`organization`:

| Campo | Tipo | Significato |
| --- | --- | --- |
| `id` | intero | Numero dell'organizzazione |
| `name` | testo | Nome |
| `slug` | testo | Nome breve univoco |
| `organization_type` | testo | `OSA` (operatore del settore alimentare) o `CONSULTANT` (studio di consulenza) |
| `is_active` | booleano | Falso se l'organizzazione è disattivata |
| `created_at` | data e ora | Quando è stata creata |
| `deleted_at` | data e ora o null | Quando è stata cancellata (null = no) |
| `plan_slug` | testo o null | Il piano di abbonamento (codice) |
| `plan_name` | testo o null | Il piano di abbonamento (nome) |

Ogni elemento di `members` (tutti i membri di sempre, anche usciti):

| Campo | Tipo | Significato |
| --- | --- | --- |
| `user_id` | intero | Numero del membro: è il valore dei campi `*_user_id` (e `published_by`, `verified_by`…) nei dati |
| `first_name` | testo | Nome (vuoto per un account cancellato) |
| `last_name` | testo | Cognome (vuoto per un account cancellato) |
| `email` | testo o null | Email; null per gli operatori (che accedono senza email) e per gli account cancellati |
| `role` | testo | Ruolo nell'organizzazione (es. `owner` titolare, `admin`, `member`) |
| `user_kind` | testo | `standard`, `operator` (operatore dell'app) o `staff` |
| `joined_at` | data e ora | Quando è entrato nell'organizzazione |
| `left_at` | data e ora o null | Quando ne è uscito (null = ancora dentro) |
| `status` | testo | Stato (vedi sotto) |

| Stato | Significato |
| --- | --- |
| `active` | membro attivo |
| `removed` | uscito dall'organizzazione |
| `disabled` | account disattivato |
| `deleted` | account cancellato: resta solo il numero, per leggere i registri |

## I dati: `dati/<tipo>.jsonl`

| Tipo | Natura | Contenuto |
| --- | --- | --- |
| [`site`](https://eleccp.com/it/formato-archivio#tipo-site) | registro | Le sedi dell'organizzazione (i locali in cui si lavora). |
| [`site_assignment`](https://eleccp.com/it/formato-archivio#tipo-site-assignment) | registro | Quali membri lavorano in quale sede. Nessuna riga per un membro = tutte le sedi. |
| [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) | registro | I fornitori. |
| [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) | registro | I luoghi di conservazione (frigoriferi, celle, dispense…). |
| [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) | registro | Le attrezzature (abbattitori, forni, sonde…). |
| [`catalog_product`](https://eleccp.com/it/formato-archivio#tipo-catalog-product) | registro | Il catalogo dei prodotti che l'attività prepara (ricette). |
| [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) | registro | I ricevimenti della merce e gli scontrini d'acquisto. |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | registro | I lotti ricevuti: una riga per prodotto ricevuto in un ricevimento. |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | registro | Le confezioni aperte (con la data limite dopo l'apertura). |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | registro | Le schede di produzione: che cosa si è preparato, quando e con che cosa. |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | registro | Gli ingredienti di ogni scheda di produzione, con la loro fonte. |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | registro | Le unità conservate: le porzioni di una preparazione messe da parte con la loro etichetta. |
| [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) | registro | I lotti di produzione: la partita a cui appartengono le preparazioni. |
| [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) | registro | La storia degli stati di lotti, unità conservate e confezioni aperte. |
| [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) | registro | I tipi di registrazione del piano di autocontrollo (temperature, pulizie…). |
| [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) | registro | Le versioni del piano di autocontrollo di ogni sede. |
| [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) | registro | I punti di controllo di ogni versione del piano. |
| [`plan_suspension`](https://eleccp.com/it/formato-archivio#tipo-plan-suspension) | registro | I periodi in cui il piano, o un suo punto, è stato sospeso. |
| [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) | registro | Le registrazioni che il piano si aspettava, finestra per finestra, con il loro esito. |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | registro | Le registrazioni dei controlli (misure, verifiche, pulizie…). |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | registro | Le non conformità e la loro gestione fino alla chiusura. |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | registro | Il registro delle etichette stampate. |
| [`duplicate_verification`](https://eleccp.com/it/formato-archivio#tipo-duplicate-verification) | registro | Le verifiche «sono la stessa merce?» fra due lotti ricevuti. |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | registro | I recuperi dell'invenduto esposto come ingrediente. |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | registro | I richiami e i fermi della merce, con gli esiti per elemento. |
| [`record_version`](https://eleccp.com/it/formato-archivio#tipo-record-version) | storico | Lo storico delle correzioni: ogni riga è un record com'era PRIMA di una correzione. |
| [`collision_resolution`](https://eleccp.com/it/formato-archivio#tipo-collision-resolution) | registro del server | Le decisioni prese su un lotto che arrivava doppio da due telefoni. |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | registro del server | Le ragioni per cui certi documenti vanno conservati (richiami, validazioni, vincoli di legge). |
| [`recall_item_outcome`](https://eleccp.com/it/formato-archivio#tipo-recall-item-outcome) | registro del server | Gli esiti di un richiamo per ogni elemento fermato (sono anche dentro `recall`). |
| [`site_access_code_rotation`](https://eleccp.com/it/formato-archivio#tipo-site-access-code-rotation) | registro del server | Quando è stato cambiato il codice di sede che sblocca le etichette. |
| [`site_reactivation`](https://eleccp.com/it/formato-archivio#tipo-site-reactivation) | registro del server | Le riattivazioni di sedi disattivate. |
| [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) | registro del server | I documenti di validazione in uso (es. la validazione di un processo) e la loro cessazione. |
| [`file`](https://eleccp.com/it/formato-archivio#tipo-file) | elenco dei file | L'elenco di ogni file citato dai dati, con dove compare e se è protetto. |

Per ogni campo: il **tipo** (*o null* se può mancare), il **significato**, i **valori ammessi** o l'**unità** dove esistono, e il tipo di dato a cui **rimanda** quando porta l'identificativo di un altro record.

### `site`

Le sedi dell'organizzazione (i locali in cui si lavora). File: `dati/site.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `name` | testo | Nome della sede |  |  |
| `address` | testo | Indirizzo |  |  |
| `timezone` | testo | Fuso orario della sede (IANA, es. «Europe/Rome»): le date locali si contano su questo |  |  |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |
| `is_default` | booleano | Vero per la sede proposta per prima |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `created_by_user_id` | intero o null | Chi l'ha creato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `created_by_display_name` | testo | Nome di chi l'ha creato, com'era in quel momento |  |  |
| `created_device_id` | testo | Dispositivo da cui è stato creato |  |  |
| `updated_by_user_id` | intero o null | Chi l'ha modificato per ultimo: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `updated_by_display_name` | testo | Nome di chi l'ha modificato per ultimo, com'era in quel momento |  |  |
| `updated_device_id` | testo | Dispositivo da cui è stato modificato per ultimo |  |  |
| `updated_at` | data e ora | Quando la riga è stata modificata l'ultima volta sul server |  |  |
| `qr_public_base_url` | testo | L'indirizzo di base dei codici QR stampati |  |  |

### `site_assignment`

Quali membri lavorano in quale sede. Nessuna riga per un membro = tutte le sedi. File: `dati/site_assignment.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `user_id` | intero | Chi è il membro: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `assigned_by` | intero | Chi ha assegnato la sede: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `deleted_at` | data e ora o null | Quando l'assegnazione è stata tolta (null = in vigore) |  |  |
| `revoked_by_user_id` | intero o null | Chi l'ha revocato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `revoked_by_display_name` | testo | Nome di chi l'ha revocato, com'era in quel momento |  |  |
| `revoked_device_id` | testo | Dispositivo da cui è stato revocato |  |  |
| `revoked_at` | data e ora o null | Quando è stato revocato |  |  |

### `supplier`

I fornitori. File: `dati/supplier.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `name` | testo | Nome o ragione sociale |  |  |
| `address` | testo | Indirizzo |  |  |
| `vat_number` | testo | Partita IVA |  |  |
| `tax_code` | testo | Codice fiscale |  |  |
| `contacts` | oggetto JSON | Recapiti (telefono, email, referente…) |  |  |
| `usual_supplies` | testo | Che cosa fornisce di solito |  |  |
| `compliance_docs` | testo | Documenti di conformità del fornitore (note) |  |  |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |
| `identification_incomplete` | booleano | Vero se manca l'indirizzo del fornitore |  |  |
| `identification_missing` | booleano | Vero se mancano indirizzo, partita IVA e codice fiscale insieme |  |  |

### `storage_location`

I luoghi di conservazione (frigoriferi, celle, dispense…). File: `dati/storage_location.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `name` | testo | Nome del luogo di conservazione |  |  |
| `kind` | testo | Tipo (frigorifero, congelatore, dispensa…) |  |  |
| `icon` | testo | Icona scelta nell'app |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |

### `equipment`

Le attrezzature (abbattitori, forni, sonde…). File: `dati/equipment.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `name` | testo | Nome dell'attrezzatura |  |  |
| `kind` | testo | Tipo di attrezzatura |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `storage_location_id` | uuid o null | Luogo di conservazione in cui si trova, se è uno |  | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |

### `catalog_product`

Il catalogo dei prodotti che l'attività prepara (ricette). File: `dati/catalog_product.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `name` | testo | Nome del prodotto |  |  |
| `expected_ingredients` | lista JSON | Ingredienti previsti dalla ricetta |  |  |
| `instructions` | testo | Istruzioni di preparazione |  |  |
| `suggested_shelf_life_days` | intero o null | Durata proposta per il prodotto finito | unità: giorni |  |
| `storage_conditions` | testo | Condizioni di conservazione dichiarate (es. «0-4 °C») |  |  |
| `photo_media_id` | uuid o null | Foto del prodotto |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `expiry_notice_days_override` | intero o null | Con quanti giorni d'anticipo avvisare della scadenza (null = il valore generale) | unità: giorni |  |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |

### `delivery`

I ricevimenti della merce e gli scontrini d'acquisto. File: `dati/delivery.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `supplier_id` | uuid | Fornitore |  | [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `delivered_at` | data e ora | Quando la merce è arrivata |  |  |
| `dispatch_date` | data o null | Data di spedizione come risulta dal documento (null = non trascritta; mai dedotta) |  |  |
| `document_ref` | testo | Estremi del documento di trasporto o della fattura |  |  |
| `judgement` | testo | Giudizio complessivo sul ricevimento | `conforme`, `non_conforme` |  |
| `checks` | oggetto JSON | Esiti dei controlli al ricevimento (controllo → esito) |  |  |
| `voice_transcript` | testo | Trascrizione della nota vocale, confermata dall'operatore |  |  |
| `is_purchase_evidence` | booleano | Vero se è uno scontrino d'acquisto invece di un ricevimento con lotti |  |  |
| `exhausted_at` | data e ora o null | Quando lo scontrino è stato dichiarato esaurito (null = ancora utilizzabile) |  |  |
| `exhausted_reopen_reason` | testo | Motivo con cui uno scontrino esaurito è stato rimesso in uso |  |  |
| `exhausted_by_recall_id` | uuid o null | Il richiamo che l'ha esaurito, se l'esaurimento è dovuto a un richiamo |  | [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) |
| `recalled_products` | lista JSON | Nomi dei prodotti di questo scontrino oggetto di un richiamo |  |  |
| `purchased_products` | lista JSON | Nomi dei prodotti acquistati, se dichiarati |  |  |

### `incoming_lot`

I lotti ricevuti: una riga per prodotto ricevuto in un ricevimento. File: `dati/incoming_lot.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `delivery_id` | uuid | Ricevimento (o scontrino) a cui si riferisce |  | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| `supplier_id` | uuid | Fornitore |  | [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `product_description` | testo | Prodotto ricevuto |  |  |
| `lot_code` | testo o null | Codice di lotto del produttore (vuoto = lotto senza codice, un'anomalia) |  |  |
| `has_anomaly` | booleano | Vero se il lotto presenta un'anomalia documentata |  |  |
| `anomaly_reason` | testo | Descrizione dell'anomalia |  |  |
| `quantity` | numero decimale (scritto come testo) o null | Quantità ricevuta |  |  |
| `unit` | testo | Unità della quantità (kg, g, l, ml, pz, confezioni…) |  |  |
| `package_content` | testo | Contenuto di una confezione, quando l'unità è un imballo (es. «2 kg») |  |  |
| `quantity_missing` | booleano | Vero se manca la quantità o la sua unità |  |  |
| `unit_kind` | testo | Se l'unità misura la merce o conta imballi (vuoto = unità fuori vocabolario o assente) | `misura`, `confezionamento`, vuoto |  |
| `durability_date` | data o null | Data di durabilità (scadenza o termine minimo di conservazione) |  |  |
| `durability_kind` | testo | Che cosa indica la data di durabilità: scadenza o termine minimo di conservazione | `scadenza`, `TMC` |  |
| `storage_location_id` | uuid o null | Dove è conservata la merce |  | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| `arrival_temperature` | numero decimale (scritto come testo) o null | Temperatura misurata all'arrivo | unità: °C |  |
| `checks` | oggetto JSON | Esiti dei controlli sul lotto (controllo → esito) |  |  |
| `status` | testo | Stato del lotto | `accettato`, `aperto`, `bloccato`, `disponibile`, `esaurito`, `non_conforme`, `reso`, `ricevuto`, `scaduto`, `scartato` |  |
| `blocked_reason` | testo | Motivo del fermo, se bloccato |  |  |
| `consolidated_into_id` | uuid o null | Il lotto in cui questo è stato consolidato (era lo stesso lotto registrato due volte) |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `consolidation_reason` | testo | Motivo del consolidamento |  |  |
| `qr_url` | testo | L'indirizzo contenuto nel codice QR stampato sull'etichetta |  |  |

### `open_ingredient`

Le confezioni aperte (con la data limite dopo l'apertura). File: `dati/open_ingredient.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `source_kind` | testo | Da dove viene la confezione: da un lotto ricevuto o da uno scontrino | `incoming_lot`, `purchase_evidence` |  |
| `source_lot_id` | uuid o null | Lotto ricevuto da cui viene (se la fonte è un lotto) |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `source_delivery_id` | uuid o null | Scontrino da cui viene (se la fonte è uno scontrino) |  | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| `declared_product_description` | testo | Il prodotto come dichiarato dall'operatore, quando la fonte è uno scontrino |  |  |
| `container_code` | testo o null | Codice breve della confezione, quando la merce non ha un lotto |  |  |
| `container_code_duplicate` | booleano | Vero se un'altra confezione porta lo stesso codice (accettata e segnalata) |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `opened_at` | data e ora | Quando è stata aperta |  |  |
| `finished_at` | data e ora o null | Quando è stata finita (null = ancora in uso, o finita prima che il dato esistesse) |  |  |
| `status` | testo | Stato della confezione | `aperto`, `finito`, `richiamato`, `bloccato`, `scartato`, `reso` |  |
| `status_reason` | testo | Motivo dell'ultimo fermo o rientro |  |  |
| `original_durability_date` | data o null | Data di durabilità del lotto al momento dell'apertura |  |  |
| `source_revision` | intero o null | Revisione della fonte al momento dell'uso: dice su quale versione del record si è deciso |  |  |
| `after_opening_date` | data o null | Data limite di consumo dopo l'apertura (null = non confermata) |  |  |
| `proposed_from` | data o null | Data da cui l'app ha calcolato la data limite proposta |  |  |
| `storage_location_id` | uuid o null | Dove è conservata la merce |  | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| `storage_conditions` | testo | Condizioni di conservazione dichiarate (es. «0-4 °C») |  |  |
| `qr_url` | testo | L'indirizzo contenuto nel codice QR stampato sull'etichetta |  |  |

### `production_sheet`

Le schede di produzione: che cosa si è preparato, quando e con che cosa. File: `dati/production_sheet.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `display_kind` | testo | Il nome del tipo di record come lo mostra l'app |  |  |
| `status` | testo | Stato della scheda: bozza o confermata (una scheda confermata non cambia più) | `bozza`, `confermata` |  |
| `catalog_product_id` | uuid o null | Prodotto del catalogo preparato, se scelto dal catalogo |  | [`catalog_product`](https://eleccp.com/it/formato-archivio#tipo-catalog-product) |
| `product_name` | testo | Nome del prodotto preparato |  |  |
| `produced_at` | data e ora | Quando è stato preparato |  |  |
| `finished_durability_date` | data o null | Data di durabilità del prodotto finito |  |  |
| `durability_kind` | testo | Che cosa indica la data di durabilità: scadenza o termine minimo di conservazione |  |  |
| `storage_conditions` | testo | Condizioni di conservazione dichiarate (es. «0-4 °C») |  |  |
| `process_notes` | testo | Note di lavorazione |  |  |
| `outcome` | testo o null | Esito complessivo della preparazione, se dichiarato | `venduto`, `somministrato`, `scartato`, `scaduto` |  |
| `outcome_at` | data e ora o null | Quando è avvenuto l'esito |  |  |
| `outcome_recipient` | testo | A chi è andato il prodotto (per venduto o somministrato) |  |  |
| `outcome_note` | testo | Nota sull'esito (obbligatoria per scartato e scaduto) |  |  |
| `outcome_by_user_id` | intero o null | Chi ha dichiarato l'esito: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `outcome_by_display_name` | testo | Nome di chi ha dichiarato l'esito, com'era in quel momento |  |  |
| `outcome_device_id` | testo | Dispositivo da cui è stato dichiarato l'esito |  |  |
| `outcome_recorded_at` | data e ora o null | Quando l'esito è stato registrato |  |  |
| `confirmed_by_user_id` | intero o null | Chi ha confermato la scheda: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `confirmed_by_display_name` | testo | Nome di chi ha confermato la scheda, com'era in quel momento |  |  |
| `confirmed_device_id` | testo | Dispositivo da cui è stata confermata la scheda |  |  |
| `confirmed_at` | data e ora o null | Quando la scheda è stata confermata |  |  |
| `duplicated_from_id` | uuid o null | Scheda da cui questa è stata duplicata |  | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `destination` | testo | Destinazione della preparazione (uso interno o vendita) | `interno`, `vendita` |  |
| `production_lot_id` | uuid o null | Lotto di produzione (la partita) a cui appartiene |  | [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) |
| `production_lot_code` | testo o null | Codice del lotto di produzione (es. «LI-T01-140926-001») |  |  |

### `production_ingredient`

Gli ingredienti di ogni scheda di produzione, con la loro fonte. File: `dati/production_ingredient.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `production_sheet_id` | uuid | Scheda di produzione a cui si riferisce |  | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| `open_ingredient_id` | uuid o null | Confezione aperta usata come fonte |  | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| `incoming_lot_id` | uuid o null | Lotto ricevuto usato come fonte |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `internal_lot_id` | uuid o null | Unità conservata usata come fonte (un semilavorato) |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `source_delivery_id` | uuid o null | Scontrino usato come fonte |  | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| `declared_product_description` | testo | Il prodotto come dichiarato dall'operatore, quando la fonte è uno scontrino |  |  |
| `marked_finished` | booleano | Vero se alla conferma la fonte è stata dichiarata finita |  |  |
| `added_via` | testo | Come è stata scelta la fonte (QR, riconoscimento testo, ricerca, scontrino) | `qr`, `ocr`, `search`, `purchase_evidence` |  |
| `exception_documented` | testo o null | Spiegazione quando l'ingrediente non ha una fonte tracciata |  |  |
| `source_revision` | intero o null | Revisione della fonte al momento dell'uso: dice su quale versione del record si è deciso |  |  |
| `usability_anomaly` | JSON o null | Perché la fonte non era più utilizzabile quando la conferma è arrivata: `{code, reason}`, null nel caso normale |  |  |
| `source_issue` | oggetto JSON o null | Com'è la fonte al momento dell'estrazione: `{code}` se c'è un problema, null altrimenti |  |  |

### `internal_lot`

Le unità conservate: le porzioni di una preparazione messe da parte con la loro etichetta. File: `dati/internal_lot.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `display_kind` | testo | Il nome del tipo di record come lo mostra l'app |  |  |
| `production_sheet_id` | uuid | Scheda di produzione da cui viene |  | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| `production_lot_id` | uuid o null | Lotto di produzione (la partita) a cui appartiene |  | [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) |
| `lot_number` | testo | Numero di lotto stampato sull'etichetta |  |  |
| `unit_seq` | intero o null | Progressivo dell'unità dentro il suo lotto di produzione |  |  |
| `unit_code` | testo o null | Codice dell'unità stampato sull'etichetta (lotto + progressivo) |  |  |
| `unit_seq_duplicate` | booleano | Vero se un'altra unità dello stesso lotto porta lo stesso progressivo |  |  |
| `outcome_conflict` | booleano | Vero se l'unità è nata da una scheda che aveva già un esito complessivo |  |  |
| `preserved_at` | data e ora o null | Quando la porzione è stata messa da parte |  |  |
| `durability_date` | data o null | Data di durabilità (scadenza o termine minimo di conservazione) |  |  |
| `durability_kind` | testo | Che cosa indica la data di durabilità: scadenza o termine minimo di conservazione |  |  |
| `storage_conditions` | testo | Condizioni di conservazione dichiarate (es. «0-4 °C») |  |  |
| `storage_location_id` | uuid o null | Dove è conservata la merce |  | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| `status` | testo | Stato dell'unità | `bloccato`, `disponibile`, `esaurito`, `recuperata`, `richiamato`, `scaduto`, `scartato`, `vendita_terminata` |  |
| `purpose` | testo | A che cosa serve: da usare in cucina o da servire/vendere | `cucina`, `servizio` |  |
| `source_unit_id` | uuid o null | L'unità esposta da cui questa è stata recuperata, se nasce da un recupero |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `is_usable` | booleano | Vero se al momento dell'estrazione si poteva usare come ingrediente |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `qr_url` | testo | L'indirizzo contenuto nel codice QR stampato sull'etichetta |  |  |
| `label` | oggetto JSON | I dati stampati sull'etichetta |  |  |

### `production_lot`

I lotti di produzione: la partita a cui appartengono le preparazioni. File: `dati/production_lot.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `display_kind` | testo | Il nome del tipo di record come lo mostra l'app |  |  |
| `kind` | testo | LI = lotto per uso interno, LE = lotto per la vendita | `LI`, `LE` |  |
| `code` | testo | Codice del lotto (es. «LI-T01-140926-001») |  |  |
| `device_code` | testo | Sigla del telefono che l'ha generato |  |  |
| `production_day` | data | Giorno di produzione, nel calendario della sede |  |  |
| `day_seq` | intero | Progressivo del lotto nel giorno |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `product_key` | testo | Il prodotto, come chiave (prodotto del catalogo o nome normalizzato) |  |  |
| `signature` | testo | Impronta dell'insieme esatto delle fonti usate |  |  |
| `code_duplicate` | booleano | Vero se un altro lotto porta lo stesso codice (accettato e segnalato) |  |  |
| `closed_at` | data e ora o null | Quando il lotto è stato chiuso |  |  |

### `lot_status_event`

La storia degli stati di lotti, unità conservate e confezioni aperte. File: `dati/lot_status_event.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `lot_id` | uuid o null | Lotto ricevuto di cui cambia lo stato |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `internal_lot_id` | uuid o null | Unità conservata di cui cambia lo stato |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `open_ingredient_id` | uuid o null | Confezione aperta di cui cambia lo stato |  | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| `from_status` | testo o null | Stato di partenza (null = nascita) | `accettato`, `aperto`, `bloccato`, `disponibile`, `esaurito`, `finito`, `non_conforme`, `recuperata`, `reso`, `ricevuto`, `richiamato`, `scaduto`, `scartato`, `vendita_terminata` |  |
| `to_status` | testo | Stato di arrivo | `accettato`, `aperto`, `bloccato`, `disponibile`, `esaurito`, `finito`, `non_conforme`, `recuperata`, `reso`, `ricevuto`, `richiamato`, `scaduto`, `scartato`, `vendita_terminata` |  |
| `reason` | testo | Motivo dichiarato |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |

### `event_type`

I tipi di registrazione del piano di autocontrollo (temperature, pulizie…). File: `dati/event_type.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `code` | testo | Codice del tipo |  |  |
| `label` | testo | Nome del tipo |  |  |
| `form` | testo | Forma della registrazione | `misura`, `checklist`, `documento` |  |
| `payload_schema` | oggetto JSON | I campi che la registrazione chiede (schema) |  |  |
| `version` | intero | Versione del tipo |  |  |
| `previous_version_id` | uuid o null | Versione precedente dello stesso tipo |  | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |
| `is_global` | booleano | Vero per un tipo della libreria comune, falso per uno dell'organizzazione |  |  |
| `copied_from` | oggetto JSON o null | Il tipo della libreria da cui è stato copiato: `{id, code, version}`, null se nato qui |  | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `created_by_user_id` | intero o null | Chi l'ha creato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `created_by_display_name` | testo | Nome di chi l'ha creato, com'era in quel momento |  |  |
| `created_device_id` | testo | Dispositivo da cui è stato creato |  |  |
| `deactivated_by_user_id` | intero o null | Chi l'ha disattivato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `deactivated_by_display_name` | testo | Nome di chi l'ha disattivato, com'era in quel momento |  |  |
| `deactivated_device_id` | testo | Dispositivo da cui è stato disattivato |  |  |
| `deactivated_at` | data e ora o null | Quando è stato disattivato |  |  |

### `plan_version`

Le versioni del piano di autocontrollo di ogni sede. File: `dati/plan_version.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `version_number` | intero | Numero della versione (assegnato alla pubblicazione) |  |  |
| `status` | testo | Stato della versione | `bozza`, `pubblicata`, `sostituita`, `archiviata` |  |
| `effective_from` | data o null | Data da cui la versione è dichiarata in vigore |  |  |
| `published_by` | intero o null | Chi ha pubblicato la versione: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `published_at` | data e ora o null | Quando è stata pubblicata |  |  |
| `notes` | testo | Note |  |  |
| `origin` | testo | Chi l'ha redatta (es. «osa») |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `created_by_user_id` | intero o null | Chi l'ha creato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `created_by_display_name` | testo | Nome di chi l'ha creato, com'era in quel momento |  |  |
| `created_device_id` | testo | Dispositivo da cui è stato creato |  |  |
| `updated_by_user_id` | intero o null | Chi l'ha modificato per ultimo: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `updated_by_display_name` | testo | Nome di chi l'ha modificato per ultimo, com'era in quel momento |  |  |
| `updated_device_id` | testo | Dispositivo da cui è stato modificato per ultimo |  |  |

### `control_point`

I punti di controllo di ogni versione del piano. File: `dati/control_point.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `lineage_id` | uuid | Identità del controllo attraverso le versioni del piano (uguale da una versione all'altra) |  |  |
| `plan_version_id` | uuid | Versione del piano di autocontrollo a cui si riferisce |  | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| `event_type_id` | uuid | Tipo di registrazione |  | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| `event_type_version` | intero | Versione del tipo di registrazione in vigore in quel momento |  |  |
| `name` | testo | Nome del punto di controllo |  |  |
| `storage_location_id` | uuid o null | Luogo di conservazione controllato |  | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| `equipment_id` | uuid o null | Attrezzatura controllata |  | [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) |
| `origin` | testo | Natura del punto: punto critico di controllo (CCP) o prerequisito/buona prassi | `CCP`, `PRP-GHP`, `verifica` |  |
| `is_ccp` | booleano | Vero se una deviazione su questo punto è grave |  |  |
| `corrective_action` | testo | Azione correttiva |  |  |
| `missing_monitoring_action` | testo | Che cosa fare quando il controllo non è stato registrato (dal piano di autocontrollo) |  |  |
| `recovery_allowed` | booleano | Vero se l'invenduto esposto qui può tornare a essere un ingrediente |  |  |
| `recovery_max_exposure_hours` | intero o null | Oltre quante ore di esposizione il recupero non è più ammesso | unità: ore |  |
| `block_lot_on_deviation` | booleano | Vero se una deviazione deve fermare la merce |  |  |
| `report_retention_months` | intero o null | Quanto conservare i referti di questo controllo (null = da definire) | unità: mesi |  |
| `report_retention_start` | testo | Da quando decorre la conservazione dei referti | `registrazione`, `fine_anno` |  |
| `is_active` | booleano | Falso se disattivato: resta a registro ma non si usa più |  |  |
| `limit` | oggetto JSON | Il limite da rispettare (forma e valori) |  |  |
| `frequency` | oggetto JSON | Ogni quanto va registrato il controllo |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |

### `plan_suspension`

I periodi in cui il piano, o un suo punto, è stato sospeso. File: `dati/plan_suspension.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `plan_version_id` | uuid | Versione del piano di autocontrollo a cui si riferisce |  | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| `control_point_id` | uuid o null | Punto sospeso (null = tutto il piano) |  | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| `from_date` | data | Primo giorno di sospensione |  |  |
| `to_date` | data | Ultimo giorno di sospensione |  |  |
| `reason` | testo | Motivo dichiarato |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `created_by_user_id` | intero o null | Chi l'ha creato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `created_by_display_name` | testo | Nome di chi l'ha creato, com'era in quel momento |  |  |
| `created_device_id` | testo | Dispositivo da cui è stato creato |  |  |
| `status` | testo | Stato della sospensione | `attiva`, `annullata` |  |
| `cancelled_at` | data e ora o null | Quando è stato annullato (null = non annullato) |  |  |
| `cancelled_by_user_id` | intero o null | Chi l'ha annullato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `cancelled_by_display_name` | testo | Nome di chi l'ha annullato, com'era in quel momento |  |  |
| `cancelled_device_id` | testo | Dispositivo da cui è stato annullato |  |  |
| `cancellation_reason` | testo | Motivo dell'annullamento |  |  |

### `expected_registration`

Le registrazioni che il piano si aspettava, finestra per finestra, con il loro esito. File: `dati/expected_registration.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `control_point_id` | uuid | Punto di controllo del piano a cui si riferisce |  | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| `window_start` | data e ora | Inizio della finestra in cui la registrazione era attesa |  |  |
| `window_end` | data e ora | Fine della finestra |  |  |
| `status` | testo | Esito: in attesa, soddisfatta o mancante | `attesa`, `soddisfatta`, `mancante` |  |
| `satisfied_by_event_id` | uuid o null | La registrazione che l'ha soddisfatta |  | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| `nc_id` | uuid o null | La non conformità aperta perché è mancata |  | [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |

### `event`

Le registrazioni dei controlli (misure, verifiche, pulizie…). File: `dati/event.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `event_type_id` | uuid | Tipo di registrazione |  | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| `event_type_version` | intero | Versione del tipo di registrazione in vigore in quel momento |  |  |
| `control_point_id` | uuid o null | Punto di controllo del piano a cui si riferisce |  | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| `esito` | testo | Esito della registrazione (calcolato dal limite per le misure) | `conforme`, `non_conforme`, `na` |  |
| `payload` | oggetto JSON | I valori registrati (misure, risposte), nella forma del tipo di registrazione |  |  |
| `incoming_lot_id` | uuid o null | Lotto ricevuto a cui si riferisce |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `internal_lot_id` | uuid o null | Unità conservata a cui si riferisce |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `production_sheet_id` | uuid o null | Scheda di produzione a cui si riferisce |  | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| `open_ingredient_id` | uuid o null | Confezione aperta a cui si riferisce |  | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| `storage_location_id` | uuid o null | Luogo di conservazione controllato |  | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| `equipment_id` | uuid o null | Attrezzatura a cui si riferisce |  | [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) |
| `plan_version_id` | uuid o null | Versione del piano di autocontrollo a cui si riferisce |  | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| `point_snapshot` | oggetto JSON | Il punto di controllo com'era al momento della registrazione (limite compreso) |  |  |
| `expected_registration_id` | uuid o null | Registrazione attesa dal piano a cui si riferisce |  | [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) |
| `site_id` | uuid o null | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `off_plan` | booleano | Vero se è una registrazione fuori dal piano |  |  |

### `non_conformity`

Le non conformità e la loro gestione fino alla chiusura. File: `dati/non_conformity.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `origin` | testo | Area in cui è nata | `CCP`, `PRP-GHP`, `verifica`, `ricevimento`, `altra` |  |
| `severity` | testo | Gravità | `alta`, `media`, `bassa` |  |
| `description` | testo | Descrizione |  |  |
| `source` | testo | Come è nata: a mano, da una misura fuori limite, da una registrazione mancante… | `auto_fuori_limite`, `auto_registrazione_mancante`, `manuale`, `conferma_offline_fonte_non_utilizzabile`, `auto_recupero_invenduto`, `auto_durata_preparazione` |  |
| `control_point_id` | uuid o null | Punto di controllo del piano a cui si riferisce |  | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| `event_id` | uuid o null | La registrazione che l'ha fatta nascere |  | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| `expected_registration_id` | uuid o null | La registrazione mancata che l'ha fatta nascere |  | [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) |
| `incoming_lot_id` | uuid o null | Lotto ricevuto a cui si riferisce |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `internal_lot_id` | uuid o null | Unità conservata a cui si riferisce |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `open_ingredient_id` | uuid o null | Confezione aperta a cui si riferisce |  | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| `delivery_id` | uuid o null | Ricevimento (o scontrino) a cui si riferisce |  | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| `production_sheet_id` | uuid o null | Scheda di produzione a cui si riferisce |  | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| `immediate_action` | testo | Azione immediata |  |  |
| `corrective_action` | testo | Azione correttiva |  |  |
| `missing_monitoring_action` | testo | Che cosa il piano prescrive quando il controllo manca (dal punto di controllo) |  |  |
| `assignee_user_id` | intero o null | Chi deve occuparsene: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `assignee_display_name` | testo | Nome di chi deve occuparsene, com'era in quel momento |  |  |
| `due_date` | data o null | Entro quando va gestita |  |  |
| `taken_over_by` | intero o null | Chi l'ha presa in carico: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `taken_over_by_display_name` | testo | Nome di chi l'ha presa in carico, com'era in quel momento |  |  |
| `taken_over_at` | data e ora o null | Quando è stata presa in carico |  |  |
| `missing_case` | testo | Che cosa è successo, per una registrazione mancante | `non_eseguito`, `eseguito_non_registrato`, `non_accertabile` |  |
| `product_outcome` | testo | Che cosa è stato deciso sul prodotto, per una registrazione mancante | `nessun_prodotto`, `rilasciato`, `rilavorato`, `reso`, `scartato`, `altra_destinazione` |  |
| `late_control_event_id` | uuid o null | Il controllo fatto in ritardo collegato come evidenza |  | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| `late_control_revision` | intero o null | Revisione di quel controllo su cui si è deciso |  |  |
| `affected_items` | lista JSON | La merce coinvolta: `[{kind, id, blocked_at}]` (kind è il tipo del record, id il suo identificativo) |  |  |
| `affected_declared_at` | data e ora o null | Quando è stata dichiarata la merce coinvolta (null = non ancora dichiarata) |  |  |
| `verification_note` | testo | Verifica dell'efficacia prima della chiusura |  |  |
| `verified_by` | intero o null | Chi ha verificato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `verified_by_display_name` | testo | Nome di chi ha verificato, com'era in quel momento |  |  |
| `verified_at` | data e ora o null | Quando è stata verificata |  |  |
| `status` | testo | Stato della non conformità | `aperta`, `in_lavorazione`, `in_verifica`, `chiusa`, `annullata` |  |
| `cancellation_reason` | testo | Motivo dell'annullamento |  |  |
| `site_id` | uuid o null | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |

### `label_print_log`

Il registro delle etichette stampate. File: `dati/label_print_log.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `record_kind` | testo | Che cosa è stato etichettato | `open_ingredient`, `internal_lot`, `incoming_lot` |  |
| `open_ingredient_id` | uuid o null | Confezione aperta a cui si riferisce |  | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| `internal_lot_id` | uuid o null | Unità conservata a cui si riferisce |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `incoming_lot_id` | uuid o null | Lotto ricevuto a cui si riferisce |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `printer_ref` | testo | Stampante usata |  |  |
| `copies` | intero | Numero di copie |  |  |
| `outcome` | testo | Esito della stampa | `ok`, `fallita` |  |
| `is_reprint` | booleano | Vero se è una ristampa |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |

### `duplicate_verification`

Le verifiche «sono la stessa merce?» fra due lotti ricevuti. File: `dati/duplicate_verification.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `external_id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `status` | testo | Stato della verifica | `aperta`, `confermato_duplicato`, `non_duplicato` |  |
| `origin` | testo | Che cosa l'ha fatta nascere (es. «correzione») |  |  |
| `left_id` | uuid | Il lotto appena corretto |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `right_id` | uuid | Il lotto che c'era già con la stessa chiave |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `triggered_by_operation_id` | uuid o null | L'operazione dell'app che l'ha fatta nascere |  |  |
| `opened_by_user_id` | intero | Chi l'ha aperta: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `opened_by_display_name` | testo | Nome di chi l'ha aperta, com'era in quel momento |  |  |
| `opened_at` | data e ora | Quando è stata aperta |  |  |
| `resolved_by_user_id` | intero o null | Chi ha deciso: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `resolved_by_display_name` | testo | Nome di chi ha deciso, com'era in quel momento |  |  |
| `resolved_at` | data e ora o null | Quando è stata presa la decisione |  |  |
| `outcome_reason` | testo | Motivo della decisione |  |  |

### `unit_recovery`

I recuperi dell'invenduto esposto come ingrediente. File: `dati/unit_recovery.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `display_kind` | testo | Il nome del tipo di record come lo mostra l'app |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `exposed_unit_id` | uuid | L'unità esposta (invenduta) da cui si è recuperato |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `recovered_unit_id` | uuid | L'unità nuova, da usare in cucina |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `exposure_start` | data e ora | Inizio dell'esposizione |  |  |
| `exposure_end` | data e ora | Fine dell'esposizione |  |  |
| `control_point_id` | uuid o null | Il punto del piano che ammette il recupero, se c'è |  | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| `control_point_lineage_id` | uuid o null | Identità del controllo attraverso le versioni del piano |  | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| `plan_version_id` | uuid o null | Versione del piano di autocontrollo a cui si riferisce |  | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| `event_ids` | lista JSON | Le registrazioni considerate nella valutazione |  | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| `missing_registration_ids` | lista JSON | Le registrazioni mancate nel periodo di esposizione |  | [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) |
| `measurement_event_id` | uuid o null | La misura presa al momento del recupero |  | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| `plan_compliant` | booleano | Vero se il recupero rispetta una regola del piano |  |  |
| `integrity_confirmed` | booleano | Vero se l'operatore ha confermato l'integrità del prodotto |  |  |
| `justification` | testo | Giustificazione dell'operatore |  |  |
| `deviations` | lista JSON | Le deviazioni trovate: `[{code, detail}]` |  |  |
| `nc_id` | uuid o null | La non conformità aperta per le deviazioni |  | [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) |

### `recall`

I richiami e i fermi della merce, con gli esiti per elemento. File: `dati/recall.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `attachments` | lista JSON | Allegati del record: `[{media_id, kind}]`, più chi e quando se aggiunti in un secondo momento. Il file è `file/<media_id>-<nome>` in uno dei pacchetti successivi |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `note` | testo o null | Nota libera |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `pending_attachments` | intero | Allegati annunciati ma non ancora arrivati al momento dell'estrazione |  |  |
| `evidence_complete` | booleano | Vero se tutti gli allegati annunciati sono arrivati |  |  |
| `revision` | intero | Numero di revisione: sale a ogni correzione. Le versioni superate sono nel tipo `record_version` |  |  |
| `corrected_at` | data e ora o null | Quando il record è stato corretto l'ultima volta (null = mai corretto) |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `mode` | testo | Simulazione o richiamo operativo | `simulazione`, `operativo` |  |
| `kind` | testo | Fermo interno, ritiro o richiamo al consumatore | `fermo_interno`, `ritiro`, `richiamo_consumatore` |  |
| `origin_kind` | testo | Di che tipo è la merce da cui parte il richiamo | `incoming_lot`, `internal_lot`, `production_sheet`, `purchase_evidence`, `open_ingredient` |  |
| `origin_incoming_lot_id` | uuid o null | Lotto ricevuto da cui parte |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `origin_internal_lot_id` | uuid o null | Unità conservata da cui parte |  | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| `origin_production_sheet_id` | uuid o null | Scheda di produzione da cui parte |  | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| `origin_delivery_id` | uuid o null | Scontrino da cui parte |  | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| `origin_open_ingredient_id` | uuid o null | Confezione aperta da cui parte |  | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| `origin_products` | lista JSON | Per uno scontrino: i prodotti dichiarati coinvolti |  |  |
| `impact_snapshot` | oggetto JSON | La merce fermata dal richiamo: `{stopped: {tipo: [id]}}` |  |  |
| `decision` | testo | Decisione presa |  |  |
| `actions` | testo | Azioni intraprese |  |  |
| `status` | testo | Stato del richiamo | `aperto`, `chiuso`, `annullato` |  |
| `cancel_reason` | testo | Motivo dell'annullamento |  |  |
| `cancelled_at` | data e ora o null | Quando è stato annullato (null = non annullato) |  |  |
| `cancel_report` | oggetto JSON | Che cosa l'annullamento ha rimesso in gioco e che cosa no |  |  |
| `closed_by_display_name` | testo o null | Nome di chi l'ha chiuso, com'era in quel momento |  |  |
| `closed_at` | data e ora o null | Quando è stato chiuso |  |  |
| `closed_by_user_id` | intero o null | Chi l'ha chiuso: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `outcomes` | lista JSON | Gli esiti per elemento fermato (la stessa forma del tipo `recall_item_outcome`) |  |  |

### `record_version`

Lo storico delle correzioni: ogni riga è un record com'era PRIMA di una correzione. File: `dati/record_version.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `entity_kind` | testo | Il tipo del record corretto (uno dei tipi di questo archivio) |  |  |
| `record_id` | uuid | L'identificativo del record corretto, nel file del suo tipo |  |  |
| `revision` | intero | Numero di revisione di questa versione (superata) |  |  |
| `snapshot` | JSON | Il record com'era prima della correzione, nella forma del suo tipo |  |  |
| `author_user_id` | intero | Chi ha registrato il fatto: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `author_display_name` | testo | Nome di chi ha registrato il fatto, com'era in quel momento |  |  |
| `occurred_at` | data e ora | Quando il fatto è avvenuto, come dichiarato da chi l'ha registrato |  |  |
| `server_accepted_at` | data e ora | Quando il server ha ricevuto la registrazione |  |  |
| `reason` | testo | Motivo della correzione |  |  |
| `source` | testo | Da dove è arrivata la correzione | `app`, `back-office`, `sistema` |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |

### `collision_resolution`

Le decisioni prese su un lotto che arrivava doppio da due telefoni. File: `dati/collision_resolution.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `organization_id` | intero | Numero dell'organizzazione (è lo stesso di `organizzazione.json`) |  |  |
| `operation_id` | uuid | L'operazione dell'app che portava il lotto doppio |  |  |
| `existing_lot_id` | uuid o null | Il lotto che c'era già |  | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| `choice` | testo | La decisione: collegare al lotto esistente o annullare | `link`, `cancel` |  |
| `reason` | testo | Motivo dichiarato |  |  |
| `resolved_by_user_id` | intero | Chi ha deciso: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `resolved_by_display_name` | testo | Nome di chi ha deciso, com'era in quel momento |  |  |
| `resolved_device_id` | testo | Dispositivo da cui è stata presa la decisione |  |  |
| `resolved_at` | data e ora | Quando è stata presa la decisione |  |  |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |

### `document_hold`

Le ragioni per cui certi documenti vanno conservati (richiami, validazioni, vincoli di legge). File: `dati/document_hold.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `updated_at` | data e ora | Quando la riga è stata modificata l'ultima volta sul server |  |  |
| `external_id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `organization_id` | intero | Numero dell'organizzazione (è lo stesso di `organizzazione.json`) |  |  |
| `source_kind` | testo | Da dove nasce la ragione di conservazione | `recall`, `validation`, `manual`, `plan_control`, `non_conformity` |  |
| `source_ref` | uuid | L'identificativo di ciò da cui nasce (il richiamo, la validazione…) |  |  |
| `reason` | testo | Motivo dichiarato |  |  |
| `indefinite` | booleano | Vero se va conservato senza scadenza |  |  |
| `until` | data e ora o null | Fino a quando va conservato |  |  |
| `state` | testo | Stato della ragione di conservazione | `aperto`, `chiuso`, `annullato`, `attiva`, `cessata`, `revocata`, `da_definire` |  |
| `media_ids` | lista JSON | I file protetti |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `missing_media_ids` | lista JSON | I file che risultavano mancanti |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `created_by_user_id` | intero o null | Chi l'ha creato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `created_by_display_name` | testo | Nome di chi l'ha creato, com'era in quel momento |  |  |
| `created_device_id` | testo | Dispositivo da cui è stato creato |  |  |
| `revoked_by_user_id` | intero o null | Chi l'ha revocato: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `revoked_by_display_name` | testo | Nome di chi l'ha revocato, com'era in quel momento |  |  |
| `revoked_device_id` | testo | Dispositivo da cui è stato revocato |  |  |
| `revoked_at` | data e ora o null | Quando è stato revocato |  |  |
| `revoke_reason` | testo | Motivo della revoca |  |  |
| `legal_status` | testo | Valutazione di un vincolo di legge | `none`, `pending_review`, `legal`, `released` |  |
| `legal_basis` | testo | Fondamento giuridico del vincolo |  |  |
| `legal_decided_by_user_id` | intero o null | Chi ha deciso sul vincolo di legge: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `legal_decided_by_display_name` | testo | Nome di chi ha deciso sul vincolo di legge, com'era in quel momento |  |  |
| `legal_decided_at` | data e ora o null | Quando si è deciso sul vincolo di legge |  |  |
| `legal_review_at` | data e ora o null | Quando il vincolo va riesaminato |  |  |
| `legal_until` | data e ora o null | Fino a quando vale il vincolo |  |  |
| `legal_pending_since` | data e ora o null | Da quando il vincolo attende una valutazione |  |  |
| `legal_release_reason` | testo | Motivo del rilascio del vincolo |  |  |
| `legal_extract_media_ids` | lista JSON | Estratti prodotti per il vincolo di legge |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `revision` | intero | Numero di revisione della ragione di conservazione |  |  |
| `sync_pending` | booleano | Vero se l'allineamento con l'archivio dei file era ancora in corso |  |  |
| `sync_attempts` | intero | Tentativi di allineamento con l'archivio dei file |  |  |
| `last_sync_error` | testo | Ultimo errore di allineamento |  |  |
| `synced_at` | data e ora o null | Quando è stata allineata l'ultima volta |  |  |
| `next_sync_at` | data e ora o null | Quando era previsto il prossimo allineamento |  |  |

### `recall_item_outcome`

Gli esiti di un richiamo per ogni elemento fermato (sono anche dentro `recall`). File: `dati/recall_item_outcome.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `updated_at` | data e ora | Quando la riga è stata modificata l'ultima volta sul server |  |  |
| `recall_id` | uuid | Il richiamo |  | [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) |
| `entity_kind` | testo | Il tipo dell'elemento deciso | `incoming_lot`, `internal_lot`, `open_ingredient`, `delivery` |  |
| `external_id` | uuid | L'identificativo dell'elemento deciso, nel file del suo tipo |  |  |
| `outcome` | testo | L'esito deciso per l'elemento | `scartato`, `reso`, `rilasciato`, `non_recuperabile`, `altra_causa`, `non_applicabile` |  |
| `reason` | testo | Motivo dichiarato |  |  |
| `status_event_id` | uuid o null | Il cambio di stato che l'esito ha prodotto |  | [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) |
| `decided_by_user_id` | intero | Chi ha deciso l'esito: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `decided_by_display_name` | testo | Nome di chi ha deciso l'esito, com'era in quel momento |  |  |
| `decided_device_id` | testo | Dispositivo da cui è stato deciso l'esito |  |  |
| `decided_at` | data e ora | Quando è stato deciso |  |  |
| `previous_outcome` | testo | L'esito precedente, se l'esito è stato cambiato |  |  |
| `previous_reason` | testo | Il motivo precedente |  |  |
| `previous_decided_by_user_id` | intero o null | Chi aveva deciso l'esito precedente: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `previous_decided_by_display_name` | testo | Nome di chi aveva deciso l'esito precedente, com'era in quel momento |  |  |
| `previous_decided_at` | data e ora o null | Quando era stato deciso l'esito precedente |  |  |
| `rectification_reason` | testo | Motivo dell'ultima correzione |  |  |
| `rectified_at` | data e ora o null | Quando l'esito è stato cambiato |  |  |

### `site_access_code_rotation`

Quando è stato cambiato il codice di sede che sblocca le etichette. File: `dati/site_access_code_rotation.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `updated_at` | data e ora | Quando la riga è stata modificata l'ultima volta sul server |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `rotated_by` | intero | Chi ha cambiato il codice: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `rotated_at` | data e ora | Quando è stato cambiato (il codice, vecchio o nuovo, non è mai registrato) |  |  |

### `site_reactivation`

Le riattivazioni di sedi disattivate. File: `dati/site_reactivation.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `updated_at` | data e ora | Quando la riga è stata modificata l'ultima volta sul server |  |  |
| `site_id` | uuid | Sede a cui il record appartiene |  | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| `actor_user_id` | intero | Chi ha riattivato la sede: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `actor_display_name` | testo | Nome di chi ha riattivato la sede, com'era in quel momento |  |  |
| `reason` | testo | Motivo dichiarato |  |  |

### `validation_use`

I documenti di validazione in uso (es. la validazione di un processo) e la loro cessazione. File: `dati/validation_use.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `created_at` | data e ora | Quando la riga è stata creata sul server |  |  |
| `updated_at` | data e ora | Quando la riga è stata modificata l'ultima volta sul server |  |  |
| `external_id` | uuid | Identificativo pubblico del record: è il valore con cui gli altri record lo citano |  |  |
| `organization_id` | intero | Numero dell'organizzazione (è lo stesso di `organizzazione.json`) |  |  |
| `media_id` | uuid | Il documento di validazione |  | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| `record_kind` | testo | Il tipo del record a cui è allegato |  |  |
| `record_id` | uuid | L'identificativo del record a cui è allegato |  |  |
| `description` | testo | Che cosa valida |  |  |
| `status` | testo | Stato: in uso, cessata o sostituita | `in_uso`, `cessata`, `sostituita` |  |
| `replaced_by_id` | uuid o null | La validazione che l'ha sostituita |  | [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) |
| `followup_months` | intero o null | Per quanto conservarla dopo la cessazione | unità: mesi |  |
| `followup_start` | testo | Da quando decorre la conservazione | `cessazione` |  |
| `declared_by_user_id` | intero o null | Chi l'ha dichiarata in uso: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `declared_by_display_name` | testo | Nome di chi l'ha dichiarata in uso, com'era in quel momento |  |  |
| `declared_device_id` | testo | Dispositivo da cui è stata dichiarata |  |  |
| `declared_at` | data e ora | Quando è stata dichiarata in uso |  |  |
| `ceased_at` | data e ora o null | Quando è cessata |  |  |
| `ceased_by_user_id` | intero o null | Chi l'ha dichiarata cessata: identificativo del membro |  | `organizzazione.json` → `members` (`user_id`) |
| `ceased_by_display_name` | testo | Nome di chi l'ha dichiarata cessata, com'era in quel momento |  |  |
| `ceased_device_id` | testo | Dispositivo da cui è stata dichiarata cessata |  |  |
| `cessation_reason` | testo | Motivo della cessazione |  |  |

### `file`

L'elenco di ogni file citato dai dati, con dove compare e se è protetto. File: `dati/file.jsonl`.

| Campo | Tipo | Significato | Valori ammessi / unità | Rimanda a |
| --- | --- | --- | --- | --- |
| `media_id` | uuid | Identificativo del file: l'originale è `file/<media_id>-<nome>` nel pacchetto indicato da `manifest.json` |  |  |
| `attachment_kinds` | lista JSON | Che cosa rappresenta il file (scontrino, foto della merce…) |  |  |
| `records` | lista JSON | I record che lo citano: `[{entity_kind, id}]` (al più 20; il resto è segnalato da `records_truncated`) |  |  |
| `records_truncated` | booleano | Vero se i record che lo citano sono più di quelli elencati |  |  |
| `in_versions` | booleano | Vero se compare anche in una versione superata (`record_version`) |  |  |
| `holds` | lista JSON | Le ragioni di conservazione che lo proteggono (vedi `document_hold`), con `missing` se risultava assente |  | [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) |
| `protected` | booleano | Vero se al momento dell'estrazione una ragione di conservazione lo protegge |  |  |

## Dati non compresi nell'archivio

L'archivio porta tutti i dati dell'organizzazione. Non porta due categorie di dati del servizio, elencate qui con il motivo.

**Dati tecnici del servizio.** Registri e contatori che servono al funzionamento di EleCCP (sincronizzazione, numerazioni, consumi) e non aggiungono nulla ai registri: ciò che contano o trasportano è già per intero nei dati dell'archivio.

| Dato | Motivo |
| --- | --- |
| `allowance_bucket` | crediti AI del periodo: dato di consumo del servizio, non registro HACCP |
| `changelog_entry` | canale tecnico del sync: ogni record c'è per intero nel suo kind |
| `demo_run` | storia dello scenario dimostrativo, non dell'azienda |
| `device_code_counter` | contatore tecnico dei codici offline (i codici stanno sui record) |
| `device_code_sequence` | contatore tecnico delle sigle dei telefoni (le sigle compaiono nei codici dei lotti) |
| `device_sync_checkpoint` | telemetria del dispositivo |
| `file_retention_clock` | stato tecnico dell'allineamento con media delle decorrenze di conservazione dei file (issue #239): si ricalcola dai record, che l'archivio porta per intero |
| `lot_number_counter` | contatore tecnico dei numeri di lotto (i numeri stanno sui record) |
| `organization_closure_state` | stato della chiusura: sta nella testata dell'archivio |
| `pending_anonymization` | è per PERSONA, non per organizzazione |
| `purged_organization` | tombstone della cancellazione |
| `sync_operation` | registro tecnico di deduplica del push: non è un dato HACCP |
| `usage_allocation` | consumo dei crediti AI: dato del servizio, non registro HACCP |
| `usage_event` | consumo dei crediti AI: dato del servizio, non registro HACCP |

**Dati di funzionamento interno esclusi ai sensi dell'art. 25 par. 2 lett. f del Regolamento (UE) 2023/2854** (Data Act). Sono dati specifici al funzionamento interno del servizio, la cui esportazione esporrebbe il servizio al rischio di violazione di segreti commerciali; l'esclusione è dichiarata nel contratto. Mancano anche dalle versioni superate in `record_version`.

| Dato | Motivo |
| --- | --- |
| `device_code` | l'associazione fra ogni telefono e la sigla con cui il servizio compone i codici dei lotti offline: meccanismo di funzionamento interno (la sigla resta nel codice di ogni lotto di produzione) |
| `duplicate_verification.collision_key` | la chiave interna con cui il servizio riconosce i possibili doppioni: meccanismo interno (i due lotti confrontati restano in `left_id` e `right_id`) |
| `production_lot.signature_sources` | gli elementi da cui il servizio calcola l'impronta delle fonti per raggruppare le preparazioni in un lotto: meccanismo interno (le fonti restano negli ingredienti delle schede, l'impronta in `signature`) |

## Le relazioni fra i tipi

Ogni riga dice: il campo di un tipo porta l'identificativo di un record di un altro tipo.

| Da | Campo | A |
| --- | --- | --- |
| [`site`](https://eleccp.com/it/formato-archivio#tipo-site) | `created_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`site`](https://eleccp.com/it/formato-archivio#tipo-site) | `updated_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`site_assignment`](https://eleccp.com/it/formato-archivio#tipo-site-assignment) | `user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`site_assignment`](https://eleccp.com/it/formato-archivio#tipo-site-assignment) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`site_assignment`](https://eleccp.com/it/formato-archivio#tipo-site-assignment) | `assigned_by` | `organizzazione.json` → `members` (`user_id`) |
| [`site_assignment`](https://eleccp.com/it/formato-archivio#tipo-site-assignment) | `revoked_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) | `storage_location_id` | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| [`catalog_product`](https://eleccp.com/it/formato-archivio#tipo-catalog-product) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`catalog_product`](https://eleccp.com/it/formato-archivio#tipo-catalog-product) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`catalog_product`](https://eleccp.com/it/formato-archivio#tipo-catalog-product) | `photo_media_id` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) | `supplier_id` | [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) |
| [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) | `exhausted_by_recall_id` | [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `delivery_id` | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `supplier_id` | [`supplier`](https://eleccp.com/it/formato-archivio#tipo-supplier) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `storage_location_id` | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) | `consolidated_into_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | `source_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | `source_delivery_id` | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) | `storage_location_id` | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `catalog_product_id` | [`catalog_product`](https://eleccp.com/it/formato-archivio#tipo-catalog-product) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `outcome_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `confirmed_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `duplicated_from_id` | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) | `production_lot_id` | [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `production_sheet_id` | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `open_ingredient_id` | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `incoming_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `internal_lot_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`production_ingredient`](https://eleccp.com/it/formato-archivio#tipo-production-ingredient) | `source_delivery_id` | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `production_sheet_id` | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `production_lot_id` | [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `storage_location_id` | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `source_unit_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`production_lot`](https://eleccp.com/it/formato-archivio#tipo-production-lot) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) | `lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) | `internal_lot_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) | `open_ingredient_id` | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) | `previous_version_id` | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) | `copied_from` | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) | `created_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) | `deactivated_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) | `published_by` | `organizzazione.json` → `members` (`user_id`) |
| [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) | `created_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) | `updated_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) | `plan_version_id` | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) | `event_type_id` | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) | `storage_location_id` | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) | `equipment_id` | [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) |
| [`plan_suspension`](https://eleccp.com/it/formato-archivio#tipo-plan-suspension) | `plan_version_id` | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| [`plan_suspension`](https://eleccp.com/it/formato-archivio#tipo-plan-suspension) | `control_point_id` | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| [`plan_suspension`](https://eleccp.com/it/formato-archivio#tipo-plan-suspension) | `created_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`plan_suspension`](https://eleccp.com/it/formato-archivio#tipo-plan-suspension) | `cancelled_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) | `control_point_id` | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) | `satisfied_by_event_id` | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) | `nc_id` | [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `event_type_id` | [`event_type`](https://eleccp.com/it/formato-archivio#tipo-event-type) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `control_point_id` | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `incoming_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `internal_lot_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `production_sheet_id` | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `open_ingredient_id` | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `storage_location_id` | [`storage_location`](https://eleccp.com/it/formato-archivio#tipo-storage-location) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `equipment_id` | [`equipment`](https://eleccp.com/it/formato-archivio#tipo-equipment) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `plan_version_id` | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `expected_registration_id` | [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) |
| [`event`](https://eleccp.com/it/formato-archivio#tipo-event) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `control_point_id` | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `event_id` | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `expected_registration_id` | [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `incoming_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `internal_lot_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `open_ingredient_id` | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `delivery_id` | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `production_sheet_id` | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `assignee_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `taken_over_by` | `organizzazione.json` → `members` (`user_id`) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `late_control_event_id` | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `verified_by` | `organizzazione.json` → `members` (`user_id`) |
| [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | `open_ingredient_id` | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | `internal_lot_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | `incoming_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`label_print_log`](https://eleccp.com/it/formato-archivio#tipo-label-print-log) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`duplicate_verification`](https://eleccp.com/it/formato-archivio#tipo-duplicate-verification) | `left_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`duplicate_verification`](https://eleccp.com/it/formato-archivio#tipo-duplicate-verification) | `right_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`duplicate_verification`](https://eleccp.com/it/formato-archivio#tipo-duplicate-verification) | `opened_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`duplicate_verification`](https://eleccp.com/it/formato-archivio#tipo-duplicate-verification) | `resolved_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `exposed_unit_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `recovered_unit_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `control_point_id` | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `control_point_lineage_id` | [`control_point`](https://eleccp.com/it/formato-archivio#tipo-control-point) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `plan_version_id` | [`plan_version`](https://eleccp.com/it/formato-archivio#tipo-plan-version) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `event_ids` | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `missing_registration_ids` | [`expected_registration`](https://eleccp.com/it/formato-archivio#tipo-expected-registration) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `measurement_event_id` | [`event`](https://eleccp.com/it/formato-archivio#tipo-event) |
| [`unit_recovery`](https://eleccp.com/it/formato-archivio#tipo-unit-recovery) | `nc_id` | [`non_conformity`](https://eleccp.com/it/formato-archivio#tipo-non-conformity) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `attachments` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `origin_incoming_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `origin_internal_lot_id` | [`internal_lot`](https://eleccp.com/it/formato-archivio#tipo-internal-lot) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `origin_production_sheet_id` | [`production_sheet`](https://eleccp.com/it/formato-archivio#tipo-production-sheet) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `origin_delivery_id` | [`delivery`](https://eleccp.com/it/formato-archivio#tipo-delivery) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `origin_open_ingredient_id` | [`open_ingredient`](https://eleccp.com/it/formato-archivio#tipo-open-ingredient) |
| [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) | `closed_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`record_version`](https://eleccp.com/it/formato-archivio#tipo-record-version) | `author_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`collision_resolution`](https://eleccp.com/it/formato-archivio#tipo-collision-resolution) | `existing_lot_id` | [`incoming_lot`](https://eleccp.com/it/formato-archivio#tipo-incoming-lot) |
| [`collision_resolution`](https://eleccp.com/it/formato-archivio#tipo-collision-resolution) | `resolved_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | `media_ids` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | `missing_media_ids` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | `created_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | `revoked_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | `legal_decided_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) | `legal_extract_media_ids` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`recall_item_outcome`](https://eleccp.com/it/formato-archivio#tipo-recall-item-outcome) | `recall_id` | [`recall`](https://eleccp.com/it/formato-archivio#tipo-recall) |
| [`recall_item_outcome`](https://eleccp.com/it/formato-archivio#tipo-recall-item-outcome) | `status_event_id` | [`lot_status_event`](https://eleccp.com/it/formato-archivio#tipo-lot-status-event) |
| [`recall_item_outcome`](https://eleccp.com/it/formato-archivio#tipo-recall-item-outcome) | `decided_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`recall_item_outcome`](https://eleccp.com/it/formato-archivio#tipo-recall-item-outcome) | `previous_decided_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`site_access_code_rotation`](https://eleccp.com/it/formato-archivio#tipo-site-access-code-rotation) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`site_access_code_rotation`](https://eleccp.com/it/formato-archivio#tipo-site-access-code-rotation) | `rotated_by` | `organizzazione.json` → `members` (`user_id`) |
| [`site_reactivation`](https://eleccp.com/it/formato-archivio#tipo-site-reactivation) | `site_id` | [`site`](https://eleccp.com/it/formato-archivio#tipo-site) |
| [`site_reactivation`](https://eleccp.com/it/formato-archivio#tipo-site-reactivation) | `actor_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) | `media_id` | [`file`](https://eleccp.com/it/formato-archivio#tipo-file) |
| [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) | `replaced_by_id` | [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) |
| [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) | `declared_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`validation_use`](https://eleccp.com/it/formato-archivio#tipo-validation-use) | `ceased_by_user_id` | `organizzazione.json` → `members` (`user_id`) |
| [`file`](https://eleccp.com/it/formato-archivio#tipo-file) | `holds` | [`document_hold`](https://eleccp.com/it/formato-archivio#tipo-document-hold) |

## Versioni del formato

Il numero di versione (`format_version` nei manifest e in `organizzazione.json`) **sale a ogni cambiamento di ciò che questa pagina descrive**: un file o un campo aggiunto, tolto, rinominato o che cambia significato, un valore ammesso nuovo, una struttura diversa dei pacchetti. Un archivio porta sempre la versione con cui è stato scritto; questa pagina descrive la versione corrente.

| Versione | Dal | Che cosa è cambiato |
| --- | --- | --- |
| 6 | 28 settembre 2026 | `missing[].reason` ammette `expired`: il file è stato cancellato perché la sua conservazione era finita, con la data in `missing[].expired_at` (issue #239). |
| 5 | 28 settembre 2026 | `document_hold.source_kind` ammette `non_conformity`: la scadenza dei file è sospesa mentre una non conformità è aperta (issue #238). |
| 4 | 28 settembre 2026 | Esclusi i dati di funzionamento interno del servizio (art. 25 par. 2 lett. f del Regolamento (UE) 2023/2854): il tipo `device_code` e i campi `production_lot.signature_sources` e `duplicate_verification.collision_key`, anche nelle versioni superate. |
| 3 | 28 settembre 2026 | `organizzazione.json` nel pacchetto 1 (azienda, organizzazione, membri); `format_url` nei manifest; le sezioni mancanti in `missing`. |
| 2 | 27 settembre 2026 | L'archivio in pacchetti ZIP con `manifest.json` radice e `manifest-parte.json`. |
| 1 | 27 settembre 2026 | Un solo ZIP con i dati e i file. |

In questa pagina

- [Data Act](https://eleccp.com/it/formato-archivio#data-act)

- [Com'è fatto l'archivio](https://eleccp.com/it/formato-archivio#com-e-fatto-l-archivio)

- [Regole generali](https://eleccp.com/it/formato-archivio#regole-generali)

- [LEGGIMI.txt](https://eleccp.com/it/formato-archivio#leggimi-txt)

- [manifest.json (pacchetto 1)](https://eleccp.com/it/formato-archivio#manifest-json-pacchetto-1)

- [manifest-parte.json (pacchetti 2, 3, …)](https://eleccp.com/it/formato-archivio#manifest-parte-json-pacchetti-2-3)

- [organizzazione.json (pacchetto 1)](https://eleccp.com/it/formato-archivio#organizzazione-json-pacchetto-1)

- [I dati: dati/<tipo>.jsonl](https://eleccp.com/it/formato-archivio#i-dati-dati-tipo-jsonl)

- [Dati non compresi nell'archivio](https://eleccp.com/it/formato-archivio#dati-non-compresi-nell-archivio)

- [Le relazioni fra i tipi](https://eleccp.com/it/formato-archivio#le-relazioni-fra-i-tipi)

- [Versioni del formato](https://eleccp.com/it/formato-archivio#versioni-del-formato)
