Vai al contenuto
CantiereGO

Formato di esportazione

Che cosa contiene l'archivio dei dati dello spazio di lavoro che un titolare scarica da CantiereGo: ogni file, ogni campo e lo schema JSON che lo descrive. È il registro aggiornato delle strutture e dei formati dei dati esportabili previsto dall'articolo 26 del Regolamento (UE) 2023/2854 (Data Act), per chi passa a un altro fornitore o vuole una copia completa dei propri dati.

L'archivio è un file ZIP. Contiene manifest.json, che lo descrive; tredici file JSON, uno per famiglia di dati, completi e autorevoli; anagrafiche.xlsx, l'anagrafica attiva nel formato del modello di importazione; e cinque cartelle: schemas/, presence/, timesheets/, photos/ e documents/.

Nei file JSON, in UTF-8, le chiavi sono in inglese e i valori sono come l'app li registra: gli identificativi sono UUID; gli istanti sono date e ore ISO 8601 con lo scarto dal tempo universale, i giorni AAAA-MM-GG, le ore del giorno HH:MM:SS; le scelte sono codici, che ogni schema elenca; un importo o una durata con i decimali è scritto come testo; null vuol dire che il dato non c'è. I testi scritti dall'ufficio restano come sono stati scritti.

L'ultima sezione, «Giurisdizione e accesso ai dati», dà le informazioni dell'articolo 28 dello stesso Regolamento: dove si trova l'infrastruttura con cui CantiereGo tratta i dati e quali misure tecniche, organizzative e contrattuali A176lab adotta contro l'accesso ai dati, o il loro trasferimento, da parte di autorità di paesi terzi.

Il formato e la sua versione

Il campo format del manifest dice il nome e la versione del formato: cantierego-workspace-export per l'archivio dello spazio di lavoro e cantierego-medical-export per l'archivio sanitario, entrambi alla versione 1.0.0, quella che questa pagina descrive.

La versione è semantica. Un campo o un file nuovo e facoltativo fa salire la versione minore (1.1.0); un campo tolto, rinominato o di tipo diverso, o un significato cambiato, fa una nuova versione maggiore (2.0.0), i cui schemi sono pubblicati in una cartella nuova, /formato-esportazione/2/. Gli schemi di questa pagina, sotto /formato-esportazione/1/, descrivono l'ultima versione minore della versione maggiore 1.

Ogni archivio porta con sé, nella cartella schemas/, gli schemi della versione con cui è stato scritto: il contratto viaggia con i dati.

Come si scarica, e per quanto tempo

Un titolare chiede l'archivio dalle impostazioni dello spazio di lavoro (Impostazioni › Azienda). L'app lo prepara in background e lo elenca quando è pronto; se ne prepara uno al giorno per spazio di lavoro, uno alla volta. Il file di ciascun archivio si scarica per 14 giorni dalla preparazione, e comunque non oltre l'inizio della cancellazione dello spazio di lavoro. Le stesse operazioni si fanno dall'interfaccia di programmazione dell'app, con le credenziali dell'account: la descrive il documento OpenAPI pubblicato all'indirizzo https://app.cantierego.it/api/v1/openapi.json.

Lo spazio di lavoro si chiude dalle stesse impostazioni. Dopo la chiusura i titolari possono ancora leggerlo, esportarlo e riaprirlo per almeno 30 giorni: trascorsi 30 giorni dalla chiusura, la cancellazione comincia al primo passaggio notturno e si conclude entro 40 giorni dalla chiusura. Un blocco legale sulle presenze o un blocco su un documento ferma la cancellazione e conserva ciò che trattiene.

Uno spazio di lavoro chiuso prima che valesse questa regola conserva la data che i suoi titolari hanno ricevuto alla chiusura: la sua cancellazione può cominciare 21 giorni dopo la chiusura.

I file dell'archivio

manifest.json

Il file da leggere per primo, scritto per ultimo: il formato e la sua versione, lo spazio di lavoro, l'istante e il giorno in cui l'archivio è stato scritto, quante righe ha ogni file JSON e quanti file ha ogni cartella, quanto è stato trattenuto per riservatezza sanitaria e quali file mancavano.

Sugli originali dei documenti fanno fede missing.originals e missing.originals_reason: un originale perso, o la lettura dei documenti sospesa per un incidente, lascia una revisione il cui campo file nomina un file che l'archivio non contiene.

Schema JSON: manifest.schema.json

I campi di manifest.json
CampoSignificato
formatIl formato dell'archivio.
format.nameNome del formato.
format.versionVersione del formato, semantica: una nuova voce facoltativa è una minore, una voce tolta, rinominata o di tipo diverso è una nuova maggiore.
export_idIdentificativo dell'esportazione.
workspaceLo spazio esportato.
workspace.idIdentificativo dello spazio.
workspace.nameNome.
workspace.slugNome breve nell'indirizzo dell'app.
workspace.legal_nameRagione sociale.
generated_atIstante in cui l'archivio è stato scritto.
dayIl giorno dello spazio in cui l'archivio è stato scritto.
timezoneIl fuso orario dello spazio.
app_versionLa versione dell'app che ha scritto l'archivio.
read_modeCome sono state lette le famiglie di dati: una dopo l'altra, a pagine.
read_mode_noteChe cosa comporta la lettura sequenziale.
read_mode_note.itIl testo in italiano.
read_mode_note.enIl testo in inglese.
filesPer ogni file JSON le righe scritte, per ogni cartella i file.
files.workspace.jsonRighe in workspace.json: sempre 1.
files.members.jsonMembri più inviti in members.json.
files.employers.jsonImprese in employers.json.
files.sites.jsonCantieri in sites.json.
files.workers.jsonLavoratori in workers.json.
files.vehicles.jsonMezzi in vehicles.json.
files.documents.jsonDocumenti in documents.json.
files.attendance_events.jsonTimbrature in attendance_events.json.
files.presence.jsonIntervalli in presence.json.
files.timesheet_sends.jsonInvii in timesheet_sends.json.
files.imports.jsonImportazioni in imports.json.
files.consents.jsonPrese visione in consents.json.
files.audit.jsonRighe in audit.json.
files.anagrafiche.xlsxRighe dei fogli di anagrafiche.xlsx, le intestazioni escluse: l'anagrafica attiva nelle colonne del modello di importazione.
files.schemas/Schemi nella cartella schemas/.
files.presence/Fogli mensili nella cartella presence/.
files.timesheets/File nella cartella timesheets/.
files.photos/Foto nella cartella photos/.
files.documents/Originali nella cartella documents/.
withheldQuanto l'archivio non contiene per riservatezza sanitaria.
withheld.medicalTotale dei documenti, esiti e giudizi trattenuti.
withheld.decisionsEsiti sanitari trattenuti.
withheld.documentsDocumenti sanitari trattenuti.
withheld.factsGiudizi di idoneità trattenuti perché selezionano un esito.
withheld.audit_rowsRighe del registro tolte o mascherate per riservatezza sanitaria.
withheld.by_employerIl totale trattenuto per impresa a cui risponde — un giudizio di idoneità e un esito, l'impresa per cui l'esito è stato registrato, anche se il lavoratore è poi passato a un'altra —: la chiave è l'identificativo dell'impresa, o none.
withheld.noteChe cosa è trattenuto e dove si trova.
withheld.note.itIl testo in italiano.
withheld.note.enIl testo in inglese.
missingI file che l'archivio avrebbe dovuto contenere e non ha trovato.
missing.photosLavoratori la cui foto mancava.
missing.originalsRevisioni il cui originale mancava.
missing.timesheetsPercorsi dei file di invio che mancavano.
missing.originals_reasonPerché mancano gli originali: null se ne manca solo qualcuno che l'archivio dei file non aveva più; document_reads_disabled se la lettura dei documenti era sospesa per un incidente e nessun originale è stato letto, tutti elencati in originals.

workspace.json

Un oggetto: l'anagrafica dello spazio di lavoro e la sua sede, le impostazioni delle presenze e della conformità, il suo stato (sospensione, chiusura, da quando la cancellazione può cominciare), le regole di conservazione dei documenti in ogni loro versione e le impostazioni dei canali di chat.

Schema JSON: workspace.schema.json

I campi di workspace.json
CampoSignificato
idIdentificativo dello spazio di lavoro.
slugNome breve dello spazio nell'indirizzo dell'app (/w/<slug>).
nameNome dello spazio di lavoro.
legal_nameRagione sociale.
vat_numberPartita IVA.
tax_codeCodice fiscale dell'azienda.
sdi_codeCodice destinatario SdI per la fatturazione elettronica.
pecIndirizzo di posta elettronica certificata.
addressSede dell'azienda.
address.streetVia e numero civico.
address.capCodice di avviamento postale, cinque cifre.
address.cityComune.
address.provinceSigla della provincia, due lettere.
address.countryPaese, codice ISO 3166-1 a due lettere (IT se non indicato).
phoneTelefono.
timezoneFuso orario IANA in cui lo spazio legge i suoi giorni (per esempio Europe/Rome).
settingsImpostazioni dello spazio per sezione: un oggetto vuoto finché l'ufficio non ne ha salvata una; ogni sezione presente è scritta intera.
settings.attendanceLe impostazioni delle presenze, salvate dall'ufficio.
settings.attendance.red_badge_policyUna timbratura in autonomia con il badge rosso: registrata o rifiutata.
settings.attendance.work_startInizio dell'orario di lavoro (ore locali).
settings.attendance.work_endFine dell'orario di lavoro (ore locali).
settings.attendance.break_minutesMinuti di pausa.
settings.attendance.retention_yearsAnni di conservazione delle presenze dalla fine del rapporto.
settings.attendance.legal_holdSe la cancellazione delle presenze è sospesa per un obbligo di legge.
settings.attendance.consultantIl consulente del lavoro a cui si inviano i fogli delle ore, o null.
settings.attendance.consultant.nameNome.
settings.attendance.consultant.emailEmail.
settings.attendance.consultant.noteNota.
settings.complianceLa politica della conformità, salvata da un titolare.
settings.compliance.strictSe i requisiti mancanti rendono rosso il badge invece di restare avvisi.
created_byL'account che ha creato lo spazio.
created_atIstante di creazione.
updated_atIstante dell'ultima modifica.
suspended_atIstante della sospensione decisa dalla piattaforma.
suspended_reasonIl motivo della sospensione comunicato ai titolari.
closed_atIstante della chiusura.
closed_byL'account del titolare che ha chiuso lo spazio.
closed_sourceChi ha chiuso lo spazio: un titolare o la piattaforma.
purge_afterIstante dal quale la cancellazione dello spazio chiuso può cominciare.
retention_policiesLe regole di conservazione dei documenti, ogni versione scritta dall'ufficio.
retention_policies[].idIdentificativo della regola.
retention_policies[].versionVersione della regola per la sua categoria.
retention_policies[].employer_idL'impresa, per una regola dei documenti sanitari; null altrimenti.
retention_policies[].categoryCategoria di documenti: ordinari, riservati, sanitari, dei mezzi.
retention_policies[].purposeFinalità della conservazione.
retention_policies[].triggerEvento da cui decorre il termine: fine del rapporto del lavoratore, chiusura del cantiere, archiviazione dell'impresa, fine del noleggio, archiviazione del documento.
retention_policies[].superseded_triggerPer una revisione sostituita: il termine decorre dalla sostituzione, o come per la revisione corrente.
retention_policies[].fallbackEvento di riserva quando quello principale non arriva.
retention_policies[].retention_monthsMesi di conservazione dopo l'evento.
retention_policies[].justification_refRiferimento normativo o contrattuale.
retention_policies[].review_onGiorno in cui la regola va rivista.
retention_policies[].created_byL'account che l'ha scritta.
retention_policies[].created_atIstante di creazione.
bot_settingsI canali di chat dello spazio e gli orari dei due avvisi programmati; null se non sono mai stati impostati.
bot_settings.telegram_enabledSe il canale Telegram è aperto per lo spazio.
bot_settings.whatsapp_enabledSe il canale WhatsApp è aperto per lo spazio.
bot_settings.forgotten_exit_atOra dell'avviso di uscita dimenticata.
bot_settings.office_summary_atOra del riepilogo per l'ufficio.
bot_settings.updated_byL'account che li ha impostati.
bot_settings.updated_atIstante dell'ultima modifica.

members.json

Un oggetto con cinque elenchi: i membri, attuali e passati, con il loro ruolo; gli inviti, accettati, scaduti o in attesa, mai il loro link; le chat Telegram o WhatsApp che i membri hanno collegato allo spazio; gli avvisi che hanno chiesto; ogni concessione o ritiro di un avviso.

Schema JSON: members.schema.json

I campi di members.json
CampoSignificato
membersI membri, attivi e passati.
members[].user_idIdentificativo dell'account.
members[].full_nameNome e cognome dell'account.
members[].emailEmail dell'account.
members[].phoneTelefono dell'account, in formato E.164.
members[].roleRuolo nello spazio.
members[].statusStato dell'appartenenza.
members[].created_atIstante dell'ingresso nello spazio.
members[].updated_atIstante dell'ultima modifica.
members[].ended_atIstante della fine dell'appartenenza.
invitationsGli inviti, accettati, scaduti o in attesa.
invitations[].idIdentificativo dell'invito.
invitations[].roleRuolo offerto.
invitations[].emailEmail a cui l'invito è stato spedito.
invitations[].phoneTelefono a cui l'invito è stato spedito.
invitations[].worker_idIl lavoratore a cui l'invito collega l'account.
invitations[].expires_atIstante di scadenza dell'invito.
invitations[].accepted_atIstante dell'accettazione.
invitations[].accepted_user_idL'account che ha accettato.
invitations[].invited_byL'account che ha invitato.
invitations[].created_atIstante dell'invio.
bot_linksLe chat Telegram o WhatsApp che i membri hanno collegato allo spazio.
bot_links[].idIdentificativo del collegamento.
bot_links[].user_idL'account del membro.
bot_links[].providerIl canale.
bot_links[].member_enabledSe il membro usa il canale in questo spazio.
bot_links[].office_enabledSe l'ufficio lascia aperto il canale al membro.
bot_links[].worker_idIl lavoratore a cui la chat è legata, se c'è.
bot_links[].notice_versionVersione dell'informativa del canale accettata.
bot_links[].plan_held_atIstante della sospensione per i limiti del piano.
bot_links[].created_atIstante del collegamento.
bot_links[].updated_atIstante dell'ultima modifica.
bot_subscriptionsGli avvisi che i membri hanno chiesto nello spazio, concessi o no.
bot_subscriptions[].idIdentificativo dell'iscrizione.
bot_subscriptions[].user_idL'account del membro.
bot_subscriptions[].providerIl canale.
bot_subscriptions[].purposeL'avviso: badge da guardare, documenti in scadenza, uscita dimenticata, riepilogo per l'ufficio.
bot_subscriptions[].scope_idIl collegamento della chat allo spazio.
bot_subscriptions[].grantedSe l'avviso è concesso.
bot_subscriptions[].notice_versionVersione dell'informativa accettata.
bot_subscriptions[].consent_event_idLa registrazione del consenso.
bot_subscriptions[].created_atIstante di creazione.
bot_subscriptions[].updated_atIstante dell'ultima modifica.
bot_consentsOgni concessione o ritiro di un avviso nello spazio.
bot_consents[].idIdentificativo della registrazione.
bot_consents[].scope_idIl collegamento della chat allo spazio.
bot_consents[].user_idL'account del membro.
bot_consents[].providerIl canale.
bot_consents[].actionConcessione o ritiro dell'avviso.
bot_consents[].purposeL'avviso.
bot_consents[].notice_versionVersione dell'informativa.
bot_consents[].grantedSe l'avviso è stato concesso.
bot_consents[].sourceDove è stato espresso: nell'app, nella chat privata, nella migrazione.
bot_consents[].actor_user_idL'account che l'ha registrato, se c'è.
bot_consents[].created_atIstante.

employers.json

Un elenco, un oggetto per impresa, archiviate comprese: l'impresa dello spazio, le imprese esecutrici e i lavoratori autonomi, con la patente a crediti, l'attestazione SOA e il DURC come l'ufficio li ha registrati, il blocco, l'istruzione sui documenti riservati e sanitari e chi l'impresa ha nominato con l'accesso nominativo ai suoi giudizi di idoneità: la nomina, mai un giudizio.

Schema JSON: employers.schema.json

I campi di employers.json
CampoSignificato
idIdentificativo dell'impresa.
kindImpresa o lavoratore autonomo.
is_owntrue per l'impresa dello spazio stesso.
legal_nameRagione sociale, o nome e cognome del lavoratore autonomo.
vat_numberPartita IVA.
tax_codeCodice fiscale.
addressSede.
address.streetVia e numero civico.
address.capCodice di avviamento postale, cinque cifre.
address.cityComune.
address.provinceSigla della provincia, due lettere.
address.countryPaese, codice ISO 3166-1 a due lettere (IT se non indicato).
emailEmail.
phoneTelefono.
notesNote dell'ufficio.
patente_statusStato della patente a crediti come registrato dall'ufficio.
patente_exempt_reasonMotivo dell'esenzione: attestazione SOA di classifica III o superiore, titolo equivalente di un altro Stato dell'Unione, attività non soggetta.
patente_creditsCrediti della patente.
patente_numberNumero della patente.
patente_checked_onGiorno in cui l'ufficio ha verificato la patente.
patente_exception_untilFine della deroga sui crediti.
patente_exception_reasonMotivo della deroga sui crediti.
patente_suspended_untilFine della sospensione della patente, quando l'ufficio l'ha registrata (solo con stato suspended).
soa_classClassifica dell'attestazione SOA che fonda l'esenzione (solo con motivo soa_iii).
soa_valid_untilScadenza dell'attestazione SOA (solo con motivo soa_iii).
durc_statusEsito del DURC come registrato dall'ufficio.
durc_valid_untilScadenza del DURC.
durc_document_idIl documento DURC che sostiene i dati.
durc_revision_idLa revisione del documento DURC citata.
durc_review_idLa revisione dell'ufficio che ha applicato il DURC.
blocked_atIstante del blocco dell'impresa da parte dell'ufficio.
blocked_reasonMotivo del blocco.
blocked_byL'account che ha bloccato l'impresa.
deleted_atIstante dell'archiviazione.
plan_held_atIstante della sospensione per i limiti del piano.
created_byL'account che l'ha creata.
created_atIstante di creazione.
updated_atIstante dell'ultima modifica.
document_policyL'istruzione dell'impresa sui suoi documenti riservati e sanitari: finalità, base e attivazione; null se non c'è.
document_policy.purpose_refRiferimento della finalità.
document_policy.basis_refRiferimento della base giuridica.
document_policy.controller_ackSe il titolare ha confermato l'istruzione.
document_policy.outcome_aware_sinceDa quando l'app registra gli esiti dei giudizi di idoneità.
document_policy.terms_versionVersione delle condizioni accettate.
document_policy.uploads_allowedSe i documenti sanitari si possono caricare.
document_policy.review_onGiorno in cui l'istruzione va rivista.
document_policy.updated_byL'account che l'ha scritta.
document_policy.created_atIstante di creazione.
document_policy.updated_atIstante dell'ultima modifica.
medical_accessChi l'impresa ha nominato per i suoi giudizi di idoneità, nomine ritirate comprese: la nomina, mai un giudizio.
medical_access[].idIdentificativo della nomina.
medical_access[].user_idL'account nominato.
medical_access[].can_writeSe può anche registrare i giudizi.
medical_access[].appointment_refRiferimento dell'atto di nomina.
medical_access[].granted_byL'account che ha nominato.
medical_access[].granted_atIstante della nomina.
medical_access[].revoked_byL'account che ha ritirato la nomina.
medical_access[].revoked_atIstante del ritiro.

sites.json

Un elenco, un oggetto per cantiere, archiviati compresi: i dati del cantiere e il suo orario, le imprese che vi partecipano, le assegnazioni dei lavoratori, passate comprese, i collegamenti dei tablet delegati e i codici di accesso ispettivo con le sessioni aperte con ciascuno.

Il codice di timbratura del cantiere, il token di un tablet e il codice ispettivo sono credenziali e non ci sono. Una sessione ispettiva porta l'indirizzo, mascherato, e il browser, come l'ufficio li legge nel registro degli usi del codice.

Schema JSON: sites.schema.json

I campi di sites.json
CampoSignificato
idIdentificativo del cantiere.
codeCodice del cantiere, immutabile.
nameNome del cantiere.
addressIndirizzo.
cityComune.
provinceSigla della provincia.
postal_codeCodice di avviamento postale.
client_nameCommittente.
client_tax_codeCodice fiscale o partita IVA del committente.
works_directorDirettore dei lavori.
safety_coordinatorCoordinatore per la sicurezza.
starts_onInizio dei lavori.
planned_end_onFine prevista.
actual_end_onFine effettiva.
contract_valueImporto dei lavori, in euro, scritto come testo.
statusStato del cantiere.
geo_latLatitudine del recinto geografico, come testo.
geo_lngLongitudine del recinto geografico, come testo.
geo_radius_mRaggio del recinto geografico, in metri.
geofence_enabledSe le timbrature in autonomia chiedono la posizione.
work_starts_atInizio dell'orario di lavoro (ore locali); null: quello dello spazio.
work_ends_atFine dell'orario di lavoro (ore locali); null: quello dello spazio.
break_minutesMinuti di pausa; null: quelli dello spazio.
notesNote dell'ufficio.
deleted_atIstante dell'archiviazione.
plan_held_atIstante della sospensione per i limiti del piano.
created_byL'account che l'ha creato.
created_atIstante di creazione.
updated_atIstante dell'ultima modifica.
employersLe imprese che partecipano al cantiere.
employers[].idIdentificativo della partecipazione.
employers[].employer_idL'impresa.
employers[].roleRuolo: appaltatrice, subappaltatrice o lavoratore autonomo.
employers[].subcontract_authorizationEstremi dell'autorizzazione al subappalto.
employers[].subcontract_authorized_onGiorno dell'autorizzazione al subappalto.
employers[].created_byL'account che l'ha registrata.
employers[].created_atIstante di creazione.
employers[].updated_atIstante dell'ultima modifica.
assignmentsLe assegnazioni dei lavoratori, passate comprese.
assignments[].idIdentificativo dell'assegnazione.
assignments[].worker_idIl lavoratore.
assignments[].roleMansione nel cantiere.
assignments[].starts_onInizio dell'assegnazione.
assignments[].ends_onFine dell'assegnazione.
assignments[].accreditedSe il lavoratore è accreditato nel cantiere.
assignments[].accredited_atIstante dell'accreditamento.
assignments[].accredited_byL'account che ha accreditato il lavoratore.
assignments[].created_byL'account che l'ha registrata.
assignments[].created_atIstante di creazione.
assignments[].updated_atIstante dell'ultima modifica.
gate_linksI collegamenti dei tablet delegati del cantiere; il loro token non c'è.
gate_links[].idIdentificativo del collegamento.
gate_links[].labelNome del tablet.
gate_links[].expires_atIstante di scadenza.
gate_links[].revoked_atIstante della revoca.
gate_links[].revoked_byL'account che l'ha revocato.
gate_links[].created_byL'account che l'ha creato.
gate_links[].last_used_atIstante dell'ultimo uso.
gate_links[].use_countUsi.
gate_links[].created_atIstante di creazione.
gate_links[].updated_atIstante dell'ultima modifica.
access_grantsI codici di accesso ispettivo del cantiere, con il registro dei loro usi; il codice non c'è, né alcuna sua parte.
access_grants[].idIdentificativo del codice.
access_grants[].kindPer chi: coordinatore per la sicurezza, ispettorato del lavoro, ASL, committente, altro.
access_grants[].labelIl nome del titolare, obbligatorio per altro.
access_grants[].legacySe viene dal sistema precedente.
access_grants[].expires_atIstante di scadenza.
access_grants[].revoked_atIstante della revoca.
access_grants[].revoked_byL'account che l'ha revocato.
access_grants[].created_byL'account che l'ha creato.
access_grants[].use_countSessioni aperte con il codice.
access_grants[].last_used_atIstante dell'ultimo uso.
access_grants[].created_atIstante di creazione.
access_grants[].updated_atIstante dell'ultima modifica.
access_grants[].usesLe sessioni aperte con il codice.
access_grants[].uses[].idIdentificativo della sessione.
access_grants[].uses[].started_atIstante di apertura.
access_grants[].uses[].expires_atIstante di scadenza.
access_grants[].uses[].last_seen_atIstante dell'ultima lettura.
access_grants[].uses[].ended_atIstante di chiusura.
access_grants[].uses[].ended_reasonPerché si è chiusa: scaduta, codice scaduto, codice revocato, cantiere archiviato.
access_grants[].uses[].ipIndirizzo da cui è stata aperta, mascherato.
access_grants[].uses[].user_agentIl browser da cui è stata aperta.
access_grants[].uses[].readsLetture fatte.

workers.json

Un elenco, un oggetto per lavoratore, disattivati compresi: l'anagrafica, il percorso della foto, i requisiti (la formazione e il giudizio di idoneità), le revisioni della formazione, le verifiche d'identità, il badge con il verdetto e i suoi motivi e la storia dei suoi stati. Il token che apre il badge è una credenziale e non c'è.

Un giudizio di idoneità compare, come l'ufficio lo legge senza l'accesso nominativo, solo finché non seleziona un esito; quando ne seleziona uno resta solo che esiste, il suo tipo e la sua versione, con withheld a true, e il suo contenuto esce con l'archivio sanitario. I motivi di un verdetto non nominano mai una causa sanitaria. Una verifica d'identità per i documenti sanitari compare senza il suo riferimento (verification_ref è null), che esce con l'archivio sanitario.

L'archivio riporta quello che l'ufficio vede: il campo version c'è sui requisiti, dove la pagina del lavoratore lo mostra, e non sulle altre righe, dove è solo il controllo interno delle modifiche concorrenti.

Schema JSON: workers.schema.json

I campi di workers.json
CampoSignificato
idIdentificativo del lavoratore.
employer_idL'impresa da cui dipende.
user_idL'account collegato al lavoratore, se c'è.
first_nameNome.
last_nameCognome.
tax_codeCodice fiscale, sedici caratteri.
birth_dateData di nascita.
birth_placeLuogo di nascita.
nationalityCittadinanza.
addressIndirizzo.
phoneTelefono.
emailEmail.
job_titleMansione.
hired_onData di assunzione.
employment_ended_onFine del rapporto di lavoro.
employer_changed_atIstante dell'ultimo cambio di impresa.
badge_exemptSe il lavoratore è esente dal badge.
badge_exempt_reasonMotivo dell'esenzione dal badge.
photo_updated_atIstante dell'ultima foto.
notesNote dell'ufficio.
training_basisRegola di formazione applicata: registrazione combinata precedente, formazione specifica, o aggiornamento.
training_review_requiredSe la formazione va rivista dall'ufficio prima di tornare valida.
deleted_atIstante della disattivazione.
disposed_atIstante della cancellazione dei dati del lavoratore.
plan_held_atIstante della sospensione per i limiti del piano.
created_byL'account che l'ha creato.
created_atIstante di creazione.
updated_atIstante dell'ultima modifica.
photoPercorso della foto nell'archivio (photos/<id>.jpg), o null se non c'è.
factsI requisiti del lavoratore.
facts[].idIdentificativo del requisito.
facts[].kindTipo: formazione generale, specifica, aggiornamento, preposto, altra formazione, formazione di base (registrazione combinata precedente) o giudizio di idoneità.
facts[].titleTitolo di un'altra formazione (training_other).
facts[].completed_onGiorno di conseguimento.
facts[].expires_onGiorno di scadenza; il requisito vale fino a quel giorno compreso.
facts[].referenceRiferimento dell'attestato o del documento.
facts[].noteNota dell'ufficio.
facts[].document_idIl documento che sostiene il requisito, se ce n'è uno.
facts[].created_atIstante di creazione.
facts[].updated_atIstante dell'ultima modifica.
facts[].sourceOrigine: inserito a mano, applicato dalla revisione di un documento, o importato dal sistema precedente. Null su un giudizio trattenuto.
facts[].document_revision_idLa revisione del documento citata come prova.
facts[].document_review_idLa revisione dell'ufficio che ha applicato il requisito.
facts[].claim_idL'affermazione della revisione che ha scritto il requisito.
facts[].decision_idSempre null in questo archivio: un giudizio che seleziona un esito è trattenuto, e gli esiti escono con l'archivio sanitario.
facts[].versionVersione del requisito, che cresce a ogni modifica.
facts[].providerEnte formatore che ha erogato il corso (solo formazione).
facts[].hoursDurata del corso in ore, maggiore di zero, al più un decimale (solo formazione), scritta come testo.
facts[].delivery_modeModalità di erogazione del corso (solo formazione).
facts[].placeLuogo di svolgimento del corso (solo formazione).
facts[].created_byL'account che ha registrato il requisito; resta anche su un giudizio trattenuto.
facts[].withheldtrue se il requisito è un giudizio di idoneità che seleziona un esito, trattenuto da questo archivio.
training_reviewsLe revisioni della formazione fatte dall'ufficio.
training_reviews[].idIdentificativo della revisione.
training_reviews[].kindTipo: conversione, revisione, ritiro o correzione.
training_reviews[].basis_beforeRegola di formazione prima.
training_reviews[].basis_afterRegola di formazione dopo.
training_reviews[].general_fact_idIl requisito di formazione generale considerato.
training_reviews[].specific_fact_idIl requisito di formazione specifica considerato.
training_reviews[].refresher_fact_idIl requisito di aggiornamento considerato.
training_reviews[].snapshotIstantanea dei requisiti di formazione al momento della revisione: un oggetto libero, nella forma che l'app usava in quel momento.
training_reviews[].applicability_refRiferimento che fonda la regola applicata.
training_reviews[].reviewer_idL'account che ha fatto la revisione.
training_reviews[].reviewed_atIstante della revisione.
identity_checksLe verifiche d'identità fatte dall'ufficio prima che l'app del lavoratore mostri un suo documento riservato o sanitario.
identity_checks[].idIdentificativo della verifica.
identity_checks[].user_idL'account del lavoratore verificato.
identity_checks[].scopePer quali documenti.
identity_checks[].employer_idL'impresa, per i documenti sanitari.
identity_checks[].custodian_idL'account che ha verificato.
identity_checks[].verified_atIstante della verifica.
identity_checks[].verification_refIl documento esibito o il riferimento della verifica; null per una verifica dei documenti sanitari, il cui riferimento esce con l'archivio sanitario.
identity_checks[].revoked_byL'account che l'ha ritirata.
identity_checks[].revoked_atIstante del ritiro.
badgeIl badge del lavoratore, o null se non è mai stato emesso. Il token che lo apre è una credenziale e non c'è.
badge.idIdentificativo del badge.
badge.issued_atIstante di emissione.
badge.expires_atIstante di scadenza.
badge.revoked_atIstante della revoca.
badge.revoked_reasonMotivo della revoca.
badge.revoked_byL'account che l'ha revocato.
badge.suspended_atIstante della sospensione.
badge.suspended_reasonMotivo della sospensione.
badge.suspended_byL'account che l'ha sospeso.
badge.blocked_atIstante del blocco.
badge.blocked_reasonMotivo del blocco.
badge.blocked_byL'account che l'ha bloccato.
badge.override_untilFine della deroga in corso.
badge.override_reasonMotivo della deroga.
badge.override_byL'account che ha concesso la deroga.
badge.stateVerdetto: verde, rosso o sospeso.
badge.state_reasonsI motivi del verdetto.
badge.state_reasons[].codeCodice della regola (per esempio missing_durc, training_specific_expired, override_active); overridden:<codice> per un motivo sollevato da una deroga.
badge.state_reasons[].detailIl testo che accompagna il motivo, dove la regola ne porta uno.
badge.state_reasons[].untilIl giorno a cui il motivo si riferisce: una scadenza o la fine di una deroga.
badge.warningsGli avvisi del verdetto.
badge.warnings[].codeCodice della regola (per esempio missing_durc, training_specific_expired, override_active); overridden:<codice> per un motivo sollevato da una deroga.
badge.warnings[].detailIl testo che accompagna il motivo, dove la regola ne porta uno.
badge.warnings[].untilIl giorno a cui il motivo si riferisce: una scadenza o la fine di una deroga.
badge.state_computed_atIstante del calcolo del verdetto.
badge.created_atIstante di creazione.
badge.updated_atIstante dell'ultima modifica.
badge_historyI cambi di stato del badge.
badge_history[].idIdentificativo del cambio.
badge_history[].from_stateStato prima.
badge_history[].to_stateStato dopo.
badge_history[].reasonsI motivi del nuovo stato.
badge_history[].reasons[].codeCodice della regola (per esempio missing_durc, training_specific_expired, override_active); overridden:<codice> per un motivo sollevato da una deroga.
badge_history[].reasons[].detailIl testo che accompagna il motivo, dove la regola ne porta uno.
badge_history[].reasons[].untilIl giorno a cui il motivo si riferisce: una scadenza o la fine di una deroga.
badge_history[].causeChe cosa ha mosso il verdetto.
badge_history[].actor_user_idL'account che ha agito, se c'è.
badge_history[].created_atIstante del cambio.

vehicles.json

Un elenco, un oggetto per mezzo, archiviati compresi: veicoli targati e non targati, a noleggio, macchine e attrezzature, con il cantiere in cui si trovano, la revisione, l'assicurazione e il noleggio.

Schema JSON: vehicles.schema.json

I campi di vehicles.json
CampoSignificato
idIdentificativo del mezzo.
kindTipo: veicolo targato, non targato, a noleggio, macchina, attrezzatura, altro.
nameNome.
plateTarga.
makeMarca.
modelModello.
yearAnno.
serialNumero di serie.
site_idIl cantiere in cui si trova.
inspection_kindRevisione: con scadenza, non registrata, non prevista.
inspection_expires_onScadenza della revisione.
inspection_revision_idLa revisione del documento che la prova.
insurance_kindAssicurazione: con scadenza, non registrata, non prevista.
insurance_expires_onScadenza dell'assicurazione.
insurance_revision_idLa revisione del documento che la prova.
rental_companySocietà di noleggio.
rental_refRiferimento del contratto di noleggio.
rental_starts_onInizio del noleggio.
rental_ends_onFine del noleggio.
rental_contract_document_idIl documento del contratto di noleggio.
notesNote dell'ufficio.
archived_atIstante dell'archiviazione.
plan_held_atIstante della sospensione per i limiti del piano.
created_byL'account che l'ha creato.
created_atIstante di creazione.
updated_atIstante dell'ultima modifica.

documents.json

Un elenco, un oggetto per documento ordinario o riservato non cancellato, con le sue revisioni, le decisioni e le incongruenze di conservazione, i blocchi della cancellazione e le revisioni dell'ufficio con quanto ciascuna ha affermato. L'originale di ogni revisione disponibile è nella cartella documents/, al percorso che il suo campo file indica.

I documenti sanitari, le loro revisioni e la loro storia non ci sono: escono con l'archivio sanitario.

Schema JSON: documents.schema.json

I campi di documents.json
CampoSignificato
idIdentificativo del documento.
site_idIl cantiere a cui si riferisce, se è suo.
worker_idIl lavoratore a cui si riferisce, se è suo.
employer_idL'impresa a cui si riferisce, se è sua.
vehicle_idIl mezzo a cui si riferisce, se è suo.
kindTipo di documento.
custom_kindTipo scritto dall'ufficio per un documento other.
sensitivityRiservatezza: ordinario o riservato.
current_revision_idLa revisione corrente.
current_review_idLa revisione dell'ufficio in vigore.
statusStato del documento.
archived_atIstante dell'archiviazione.
created_byL'account che l'ha creato.
created_atIstante di creazione.
updated_atIstante dell'ultima modifica.
revisionsLe revisioni del documento, in ordine.
revisions[].idIdentificativo della revisione.
revisions[].ordinalNumero d'ordine della revisione nel documento.
revisions[].original_filenameNome del file caricato.
revisions[].content_typeTipo del file (per esempio application/pdf).
revisions[].byte_lengthDimensione del file, in byte.
revisions[].sha256Impronta SHA-256 del file, in esadecimale.
revisions[].availabilityDisponibilità dell'originale.
revisions[].use_stateUso: candidata, revisionata, sostituita, ritirata.
revisions[].ready_atIstante in cui l'originale è stato accettato.
revisions[].retired_atIstante in cui la revisione è uscita dall'uso.
revisions[].document_dateData del documento.
revisions[].validity_kindValidità: con scadenza, senza scadenza, non registrata.
revisions[].expires_onScadenza del documento.
revisions[].noteNota dell'ufficio.
revisions[].retention_policy_idLa regola di conservazione applicata.
revisions[].retention_triggerL'evento della regola da cui decorre il termine, come applicato.
revisions[].retention_trigger_onIl giorno di quell'evento.
revisions[].retention_deadlineGiorno fino al quale va conservato.
revisions[].created_atIstante di creazione.
revisions[].updated_atIstante dell'ultima modifica.
revisions[].filePercorso dell'originale nell'archivio (documents/<documento>/<revisione>.<estensione>), o null se l'originale non è disponibile.
revisions[].retention_decisionsLe decisioni dell'ufficio sulla conservazione della revisione.
revisions[].retention_decisions[].idIdentificativo della decisione.
revisions[].retention_decisions[].decisionApplicare la regola, conservare, eliminare.
revisions[].retention_decisions[].policy_beforeLa regola prima.
revisions[].retention_decisions[].policy_afterLa regola dopo.
revisions[].retention_decisions[].deadline_beforeIl termine prima.
revisions[].retention_decisions[].deadline_afterIl termine dopo.
revisions[].retention_decisions[].reasonIl motivo.
revisions[].retention_decisions[].decided_byL'account che ha deciso.
revisions[].retention_decisions[].decided_atIstante della decisione.
revisions[].retention_conflictsLe incongruenze di conservazione trovate sulla revisione, risolte comprese.
revisions[].retention_conflicts[].idIdentificativo dell'incongruenza.
revisions[].retention_conflicts[].reasonPerché: la revisione prova un requisito, il soggetto è tornato attivo, l'evento non è plausibile.
revisions[].retention_conflicts[].created_atIstante in cui è stata trovata.
revisions[].retention_conflicts[].resolved_atIstante della risoluzione.
revisions[].retention_conflicts[].decision_idLa decisione che l'ha risolta.
holdsI blocchi della cancellazione posti sul documento, tolti compresi.
holds[].idIdentificativo del blocco.
holds[].authority_refRiferimento dell'autorità o dell'atto.
holds[].placed_byL'account che l'ha posto.
holds[].placed_atIstante in cui è stato posto.
holds[].review_onGiorno in cui va rivisto.
holds[].released_byL'account che l'ha tolto.
holds[].released_atIstante in cui è stato tolto.
reviewsLe revisioni dell'ufficio sul documento, con quanto ciascuna ha affermato.
reviews[].idIdentificativo della revisione.
reviews[].revision_idLa revisione del documento esaminata.
reviews[].previous_review_idLa revisione dell'ufficio precedente.
reviews[].reviewer_idL'account che l'ha fatta.
reviews[].reviewed_atIstante della revisione.
reviews[].scopeChe cosa ha fatto: archiviazione, dati, classificazione, ritiro, ripristino.
reviews[].snapshotI dati del documento come la revisione li ha visti: un oggetto libero, nella forma che l'app usava in quel momento.
reviews[].share_with_workerSe il documento è mostrato al lavoratore nella sua app.
reviews[].claimsChe cosa la revisione ha affermato del soggetto (un requisito, il DURC, una scadenza del mezzo).
reviews[].claims[].idIdentificativo dell'affermazione.
reviews[].claims[].worker_idIl lavoratore, se il soggetto è un lavoratore.
reviews[].claims[].employer_idL'impresa, se il soggetto è un'impresa.
reviews[].claims[].vehicle_idIl mezzo, se il soggetto è un mezzo.
reviews[].claims[].claim_kindChe cosa afferma.
reviews[].claims[].valuesI valori affermati (date, riferimenti): un oggetto libero, nella forma del tipo di affermazione.

attendance_events.json

Un elenco, una voce per timbratura, annullate comprese, da qualsiasi canale: il varco, l'app del lavoratore, il tablet delegato, l'inserimento manuale, le chat, l'importazione. Ogni timbratura porta il verdetto del badge di quell'istante, la distanza dal cantiere e la precisione della posizione: le coordinate non sono mai conservate.

Schema JSON: attendance_events.schema.json

I campi di attendance_events.json
CampoSignificato
idIdentificativo della timbratura.
worker_idIl lavoratore.
site_idIl cantiere.
kindEntrata o uscita.
occurred_atIstante della timbratura.
device_atIstante secondo il dispositivo, se diverso.
clock_offset_sScarto dell'orologio del dispositivo, in secondi.
offlineSe è stata registrata senza rete e inviata dopo.
channelCanale: varco, app del lavoratore, tablet delegato, inserimento manuale, WhatsApp, Telegram, importazione.
identified_byCome è stato identificato il lavoratore.
gate_link_idIl collegamento del tablet delegato, se usato.
actor_user_idL'account che ha registrato la timbratura, se c'è.
badge_stateVerdetto del badge in quell'istante.
badge_reasonsI motivi di quel verdetto.
badge_reasons[].codeCodice della regola (per esempio missing_durc, training_specific_expired, override_active); overridden:<codice> per un motivo sollevato da una deroga.
badge_reasons[].detailIl testo che accompagna il motivo, dove la regola ne porta uno.
badge_reasons[].untilIl giorno a cui il motivo si riferisce: una scadenza o la fine di una deroga.
accuracy_mPrecisione della posizione, in metri.
distance_mDistanza dal cantiere, in metri.
geofence_enforcedSe il recinto geografico è stato applicato.
justificationGiustificazione di un inserimento manuale o per codice fiscale.
justification_docRiferimento del documento a supporto.
noteNota.
presumedSe è un'entrata o un'uscita presunta dall'app.
flagsSegnalazioni sulla timbratura (per esempio clock_skew, late_sync).
voided_atIstante dell'annullamento.
voided_reasonMotivo dell'annullamento.
voided_byL'account che l'ha annullata.
ipIndirizzo da cui è arrivata la timbratura.
user_agentIl browser o l'app da cui è arrivata.
created_atIstante di registrazione.
updated_atIstante dell'ultima modifica (un annullamento, una nota).

presence.json

Un elenco, una voce per intervallo di presenza ricavato dalle timbrature: una permanenza di un lavoratore in un cantiere, con i suoi estremi, quelli presunti e la durata. I fogli mensili sono nella cartella presence/.

Schema JSON: presence.schema.json

I campi di presence.json
CampoSignificato
idIdentificativo dell'intervallo.
worker_idIl lavoratore.
site_idIl cantiere.
starts_atInizio dell'intervallo.
ends_atFine dell'intervallo; null se è ancora aperto.
in_event_idLa timbratura di entrata.
out_event_idLa timbratura di uscita.
presumed_inSe l'entrata è presunta.
presumed_outSe l'uscita è presunta.
presumed_causePerché un estremo è presunto: cambio di cantiere, fine giornata, entrata mancante.
minutesDurata in minuti; null se è ancora aperto.
flagsSegnalazioni sull'intervallo (per esempio double_in).

timesheet_sends.json

Un elenco, una voce per ogni invio dei fogli delle ore di presenza al consulente del lavoro, con il mese, il destinatario, i conteggi e l'esito. I file spediti sono nella cartella timesheets/.

Schema JSON: timesheet_sends.schema.json

I campi di timesheet_sends.json
CampoSignificato
idIdentificativo dell'invio.
period_monthIl mese, come il suo primo giorno.
site_idIl cantiere, se l'invio riguarda uno solo.
recipient_emailEmail del consulente.
worker_countLavoratori nel foglio.
hours_totalOre di presenza in totale, come testo.
presumed_countEstremi presunti nel foglio.
anomaly_countAnomalie nel foglio.
statusStato dell'invio.
errorCodice dell'errore di un invio fallito.
is_resendSe è un nuovo invio dello stesso mese.
sent_byL'account che ha inviato.
sent_atIstante dell'invio.
created_atIstante della richiesta.
updated_atIstante dell'ultima modifica.
filesPercorsi dei file spediti nell'archivio (timesheets/<id>.xlsx e .csv).

imports.json

Un elenco, una voce per importazione da foglio di calcolo, prove comprese, con il riepilogo per foglio e l'esito di ogni riga letta. Il file caricato non c'è: l'app lo cancella dopo sette giorni.

Schema JSON: imports.schema.json

I campi di imports.json
CampoSignificato
idIdentificativo dell'importazione.
created_byL'account che ha caricato il file.
file_nameNome del file caricato.
file_sizeDimensione del file, in byte.
modeProva o applicazione.
optionsLe opzioni scelte.
options.update_existingSe le righe esistenti andavano aggiornate.
statusStato.
started_atIstante di inizio.
finished_atIstante di fine.
summaryIl riepilogo, null finché l'importazione non è finita: per ogni foglio che il file conteneva (IMPRESE, CANTIERI, LAVORATORI, ASSEGNAZIONI, MEZZI) i conteggi per esito, e gli avvisi.
summary.noticesGli avvisi della lettura (per esempio un foglio saltato e perché).
summary.*I conteggi per esito delle righe del foglio.
summary.*.createdRighe che hanno creato.
summary.*.updatedRighe che hanno aggiornato.
summary.*.skippedRighe saltate.
summary.*.failedRighe in errore.
summary.*.refusedRighe rifiutate per i limiti del piano (assente nei riepiloghi scritti prima del 19 ottobre 2026).
errorCodice dell'errore di un'importazione fallita.
created_atIstante del caricamento.
updated_atIstante dell'ultima modifica.
rowsL'esito di ogni riga letta.
rows[].idIdentificativo della riga del rapporto.
rows[].sheetIl foglio.
rows[].row_numberIl numero di riga nel foglio.
rows[].keyLa chiave della riga (per esempio un codice fiscale).
rows[].outcomeEsito.
rows[].codeCodice dell'esito.
rows[].messageMessaggio in italiano.
rows[].entity_typeIl tipo di riga scritta.
rows[].entity_idLa riga scritta.
rows[].created_atIstante.

consents.json

Un elenco, una voce per ogni presa visione dell'informativa sulla geolocalizzazione da parte di un lavoratore dello spazio, data o ritirata, con la versione dell'informativa. Mai l'indirizzo o il browser da cui è arrivata.

Schema JSON: consents.schema.json

I campi di consents.json
CampoSignificato
idIdentificativo della presa visione.
worker_idIl lavoratore collegato all'account che l'ha data.
versionVersione dell'informativa.
grantedSe è stata data (true) o ritirata (false).
created_atIstante.

audit.json

Un elenco, una riga per azione registrata nello spazio, come i titolari leggono il registro delle attività: chi ha agito, su che cosa, e lo stato prima e dopo. Come quel registro non porta l'indirizzo né il browser: quelli delle righe che riguardano un account, e che l'account stesso ha scritto, sono nell'esportazione di quell'account.

La storia di un documento sanitario non c'è, e l'istantanea di una riga che riguarda un giudizio di idoneità, con o senza esito, è sostituita da {"withheld": "medical"}. La riga di un vecchio aggiornamento di un requisito che non ne nomina il tipo (worker.fact_updated) perde le date, il riferimento e la nota, e la sua istantanea porta {"withheld": "unclassified"} accanto al resto, perché potrebbe essere quella di un giudizio di idoneità. Il manifest conta queste righe in withheld.audit_rows.

Schema JSON: audit.schema.json

I campi di audit.json
CampoSignificato
idIdentificativo della riga.
actionL'azione (per esempio worker.created, badge.issued).
entity_typeIl tipo di cosa su cui si è agito.
entity_idLa cosa su cui si è agito.
actor_user_idL'account che ha agito, se c'è.
actor_kindChi ha agito: un account, il sistema, un servizio esterno, la piattaforma.
beforeLo stato prima: un oggetto libero, nella forma dell'azione; null se non c'è.
afterLo stato dopo: un oggetto libero, nella forma dell'azione; null se non c'è.
created_atIstante.

anagrafiche.xlsx

L'anagrafica attiva nei cinque fogli del modello di importazione — IMPRESE, CANTIERI, LAVORATORI, ASSEGNAZIONI, MEZZI — con le stesse intestazioni, nello stesso ordine: un formato parallelo e volutamente parziale, che si apre con qualsiasi programma per fogli di calcolo e si reimporta in CantiereGo. I file JSON restano completi e fanno fede.

I valori sono scritti come l'importazione li legge: le date come date (gg/mm/aaaa), i numeri come numeri, le scelte con le parole del modello, sì e no. Il file non ha un limite di righe suo; un foglio xlsx ne contiene al massimo 1.048.576, l'intestazione compresa, mentre i file JSON non hanno questo limite.

  • Solo l'anagrafica attiva: le imprese, i cantieri e i mezzi non archiviati, i lavoratori né disattivati né cancellati, le assegnazioni in corso o future; le righe sospese per i limiti del piano ci sono. Le righe archiviate, disattivate o cancellate e le assegnazioni finite sono solo nei file JSON: il modello non ha una colonna di stato, e una reimportazione le riporterebbe attive.
  • Restano vuote, e sono nei file JSON: formazione_base_data e formazione_base_scadenza (la registrazione combinata precedente, che l'importazione rifiuta su un lavoratore con la formazione specifica, come è ogni lavoratore che un'importazione crea), idoneita_scadenza (un dato sanitario) e la colonna id dei mezzi, che identifica un mezzo solo in questo spazio di lavoro. La formazione generale, specifica e di aggiornamento e gli altri corsi non hanno una colonna nel modello e sono solo nei file JSON; il corso del preposto c'è.
  • Il foglio IMPRESE riporta un'impresa solo se ha la partita IVA o il codice fiscale, la chiave con cui l'importazione la riconosce. Di un'altra impresa senza nessuno dei due mancano anche i lavoratori e le loro assegnazioni, che sono solo nei file JSON; i lavoratori dell'impresa dello spazio ci sono comunque.
  • I lavoratori dell'impresa dello spazio hanno vuote le colonne datore_piva e datore_cf, e l'importazione li assegna all'impresa dello spazio di destinazione. Prima di importare, inserisci la partita IVA o il codice fiscale dell'azienda nelle impostazioni dello spazio di destinazione: così la riga dell'impresa nel foglio IMPRESE aggiorna quella e non ne crea una seconda.
  • Un testo che comincia con =, +, - o @, una tabulazione o un ritorno a capo è scritto con un apostrofo davanti, perché un foglio di calcolo non lo esegua come una formula; una reimportazione conserva l'apostrofo, tranne in un numero di telefono.
  • I fogli sono letti uno dopo l'altro, non in un'unica istantanea: una riga creata mentre l'archivio si scrive può nominare un codice che un foglio letto prima non riporta.
  • Un'importazione legge un foglio di al più 5000 righe (uno più lungo è saltato) da un file di al più 10 MiB: un'anagrafica più grande si reimporta in più file, ciascuno entro questi limiti, le imprese e i cantieri prima dei lavoratori e delle assegnazioni che li nominano.
  • Reimportato nello stesso spazio di lavoro con l'aggiornamento delle righe esistenti, il file vede rifiutata, con il suo errore nel rapporto, ogni riga il cui DURC o corso del preposto è sostenuto da un documento: quei dati si correggono dalla revisione del documento. Nello stesso spazio, un lavoratore di un'impresa sospesa per i limiti del piano è rifiutato, come lo sarebbe dall'app.

schemas/

Gli schemi JSON dei file JSON dell'archivio, gli stessi pubblicati su questa pagina: manifest.schema.json e uno per ogni file, con il nome del file seguito da .schema.json.

presence/

Un file CSV per ogni mese con almeno una presenza, presence/<AAAA-MM>.csv: il foglio mensile delle ore di presenza come l'ufficio lo scarica, una riga per lavoratore, giorno e cantiere. È in italiano, separato da punti e virgola, in UTF-8 con BOM, con le ore in decimali e la virgola.

timesheets/

I file spediti al consulente del lavoro, timesheets/<id>.xlsx e timesheets/<id>.csv, byte per byte come sono partiti: riletti, mai ricostruiti. L'id è quello dell'invio in timesheet_sends.json.

photos/

La foto di ogni lavoratore che ne ha una, photos/<id>.jpg, in JPEG come l'app la conserva. L'id è quello del lavoratore in workers.json.

documents/

L'originale di ogni revisione disponibile dei documenti di documents.json, documents/<documento>/<revisione>.<estensione>, letto dalla sua versione esatta: la sua impronta SHA-256 è nel campo sha256 della revisione. Mai un documento sanitario. Una revisione ferma per un'incongruenza di conservazione aperta non porta il suo originale finché non è risolta; un originale che manca è elencato nel manifest, in missing.originals.

L'archivio sanitario

I giudizi di idoneità con un esito, gli esiti e i documenti sanitari non sono nell'archivio dello spazio di lavoro: nell'ufficio li legge solo chi l'impresa ha nominato con l'accesso nominativo ai suoi giudizi, ed escono con un archivio a parte, l'archivio sanitario, nel formato cantierego-medical-export, con la stessa versione e la stessa regola.

Lo chiede, da Impostazioni › Documenti, un membro che ha l'accesso nominativo ai giudizi di almeno un'impresa, da un accesso con la verifica in due passaggi. Copre le imprese che il suo accesso copre quando lo chiede e ancora quando l'archivio si scrive: per i loro lavoratori contiene i giudizi di idoneità, con o senza esito, gli esiti con il riferimento della revisione delle prescrizioni, i documenti sanitari con la loro storia e i loro originali, e le verifiche d'identità per i documenti sanitari con il loro riferimento, queste solo per le imprese di cui chi lo chiede legge le verifiche nell'app: tutte per un titolare, quelle di cui è referente sanitario per chi non è titolare, nessuna per chi ha un accesso in sola lettura.

Se ne chiede uno al giorno. L'archivio è di chi l'ha chiesto: lo scarica solo lui, finché ha ancora l'accesso a ogni impresa che copre, per 14 giorni dalla preparazione.

Se nessuno ha un accesso nominativo, un titolare nomina sé stesso dalla pagina dell'impresa, con la verifica in due passaggi, e chiede l'archivio: è così che l'azienda raggiunge i propri dati sanitari. Un titolare può nominarsi su uno spazio di lavoro attivo o chiuso, non su uno sospeso. Su uno spazio di lavoro sospeso o chiuso l'archivio sanitario lo chiede e lo scarica solo un titolare che abbia l'accesso nominativo: chi lo ha e non è titolare lo chieda e lo scarichi mentre lo spazio di lavoro è attivo.

Un giudizio di idoneità compare nell'archivio dello spazio di lavoro, come l'ufficio lo legge, solo finché non seleziona un esito; quando ne seleziona uno, il suo contenuto è nell'archivio sanitario.

manifest.json — archivio sanitario

Il manifest dell'archivio sanitario: il formato e la sua versione, lo spazio di lavoro, chi l'ha chiesto e le imprese che il suo accesso nominativo copriva, l'istante e il giorno in cui è stato scritto, i conteggi e quali originali mancavano, con il motivo.

Schema JSON: medical/manifest.schema.json

I campi di manifest.json — archivio sanitario
CampoSignificato
formatIl formato dell'archivio.
format.nameNome del formato.
format.versionVersione del formato, con la stessa regola dell'archivio dello spazio.
export_idIdentificativo dell'esportazione.
workspaceLo spazio esportato.
workspace.idIdentificativo dello spazio.
workspace.nameNome.
workspace.slugNome breve nell'indirizzo dell'app.
workspace.legal_nameRagione sociale.
requested_byL'account che ha chiesto l'archivio.
employersLe imprese i cui giudizi l'accesso nominativo del richiedente copriva.
employers[].idIdentificativo dell'impresa.
employers[].legal_nameRagione sociale.
generated_atIstante in cui l'archivio è stato scritto.
dayIl giorno dello spazio in cui l'archivio è stato scritto.
timezoneIl fuso orario dello spazio.
app_versionLa versione dell'app che ha scritto l'archivio.
read_modeCome sono stati letti i dati: uno dopo l'altro, a pagine.
read_mode_noteChe cosa comporta la lettura sequenziale.
read_mode_note.itIl testo in italiano.
read_mode_note.enIl testo in inglese.
filesPer ogni file JSON le righe scritte, per ogni cartella i file.
files.workers.jsonLavoratori in workers.json.
files.schemas/Schemi nella cartella schemas/.
files.documents/Originali nella cartella documents/.
missingI file che l'archivio avrebbe dovuto contenere e non ha trovato.
missing.originalsRevisioni il cui originale mancava.
missing.originals_reasonPerché mancano gli originali: null se ne manca solo qualcuno che l'archivio dei file non aveva più; document_reads_disabled se la lettura dei documenti era sospesa per un incidente e nessun originale è stato letto, tutti elencati in originals.

workers.json — archivio sanitario

Un elenco, un oggetto per lavoratore delle imprese coperte, o con un dato sanitario registrato sotto una di esse: i giudizi di idoneità, gli esiti con il loro riferimento, i documenti sanitari con le loro revisioni, le revisioni dell'ufficio, le decisioni e le incongruenze di conservazione e i blocchi, e le verifiche d'identità per i documenti sanitari con il loro riferimento delle sole imprese di cui chi l'ha chiesto legge le verifiche nell'app (tutte per un titolare, quelle di cui è referente sanitario per chi non è titolare, nessuna per chi ha un accesso in sola lettura). Ciascun dato sta sotto l'impresa per cui è stato registrato; un giudizio senza esito sotto l'impresa attuale del lavoratore.

Schema JSON: medical/workers.schema.json

I campi di workers.json — archivio sanitario
CampoSignificato
workerIl lavoratore.
worker.idIdentificativo del lavoratore.
worker.employer_idL'impresa da cui dipende.
worker.first_nameNome.
worker.last_nameCognome.
worker.tax_codeCodice fiscale, sedici caratteri.
worker.deleted_atIstante della disattivazione.
worker.disposed_atIstante della cancellazione dei dati del lavoratore.
factsI giudizi di idoneità del lavoratore.
facts[].idIdentificativo del requisito.
facts[].kindTipo: giudizio di idoneità.
facts[].titleTitolo di un'altra formazione (training_other).
facts[].completed_onGiorno di conseguimento.
facts[].expires_onGiorno di scadenza; il requisito vale fino a quel giorno compreso.
facts[].referenceRiferimento dell'attestato o del documento.
facts[].noteNota dell'ufficio.
facts[].document_idIl documento che sostiene il requisito, se ce n'è uno.
facts[].created_atIstante di creazione.
facts[].updated_atIstante dell'ultima modifica.
facts[].sourceOrigine: inserito a mano, applicato dalla revisione di un documento, o importato dal sistema precedente. Null su un giudizio trattenuto.
facts[].document_revision_idLa revisione del documento citata come prova.
facts[].document_review_idLa revisione dell'ufficio che ha applicato il requisito.
facts[].claim_idL'affermazione della revisione che ha scritto il requisito.
facts[].decision_idL'esito che il giudizio seleziona.
facts[].versionVersione del requisito, che cresce a ogni modifica.
facts[].providerEnte formatore che ha erogato il corso (solo formazione).
facts[].hoursDurata del corso in ore, maggiore di zero, al più un decimale (solo formazione), scritta come testo.
facts[].delivery_modeModalità di erogazione del corso (solo formazione).
facts[].placeLuogo di svolgimento del corso (solo formazione).
facts[].created_byL'account che ha registrato il requisito; resta anche su un giudizio trattenuto.
facts[].withheldSempre false: in questo archivio nessun giudizio è trattenuto.
decisionsGli esiti sanitari registrati.
decisions[].idIdentificativo dell'esito.
decisions[].employer_idL'impresa a cui il giudizio risponde.
decisions[].previous_decision_idL'esito che questo sostituisce.
decisions[].outcomeEsito: idoneo, idoneo con prescrizioni, non idoneo temporaneamente, non idoneo permanentemente, non classificato (precedente).
decisions[].assessed_onGiorno della visita.
decisions[].valid_untilValidità del giudizio.
decisions[].next_review_onProssima visita.
decisions[].eligibility_untilFino a quando il lavoratore è ammesso.
decisions[].boundary_basisSu che cosa si fonda il limite di ammissione.
decisions[].boundary_refRiferimento del limite.
decisions[].context_versionVersione del contesto in cui è stato registrato.
decisions[].applicabilitySe l'esito è confermato o da rivedere.
decisions[].review_refRiferimento della revisione delle prescrizioni.
decisions[].retention_policy_idLa regola di conservazione applicata.
decisions[].document_idIl documento sanitario che lo prova.
decisions[].revision_idLa revisione del documento.
decisions[].review_idLa revisione dell'ufficio.
decisions[].correction_ofL'esito che questo corregge.
decisions[].correction_refRiferimento della correzione.
decisions[].actor_idL'account che l'ha registrato.
decisions[].created_atIstante di registrazione.
decisions[].policy_review_overdueSe la regola di conservazione andava rivista.
documentsI documenti sanitari non cancellati.
documents[].idIdentificativo del documento.
documents[].kindTipo di documento.
documents[].custom_kindTipo scritto dall'ufficio per un documento other.
documents[].sensitivityRiservatezza: sempre sanitario.
documents[].medical_employer_idL'impresa a cui il documento risponde.
documents[].current_revision_idLa revisione corrente.
documents[].current_review_idLa revisione dell'ufficio in vigore.
documents[].statusStato del documento.
documents[].archived_atIstante dell'archiviazione.
documents[].created_byL'account che l'ha creato.
documents[].created_atIstante di creazione.
documents[].updated_atIstante dell'ultima modifica.
documents[].revisionsLe revisioni del documento, in ordine.
documents[].revisions[].idIdentificativo della revisione.
documents[].revisions[].ordinalNumero d'ordine della revisione nel documento.
documents[].revisions[].original_filenameNome del file caricato.
documents[].revisions[].content_typeTipo del file (per esempio application/pdf).
documents[].revisions[].byte_lengthDimensione del file, in byte.
documents[].revisions[].sha256Impronta SHA-256 del file, in esadecimale.
documents[].revisions[].availabilityDisponibilità dell'originale.
documents[].revisions[].use_stateUso: candidata, revisionata, sostituita, ritirata.
documents[].revisions[].ready_atIstante in cui l'originale è stato accettato.
documents[].revisions[].retired_atIstante in cui la revisione è uscita dall'uso.
documents[].revisions[].document_dateData del documento.
documents[].revisions[].validity_kindValidità: con scadenza, senza scadenza, non registrata.
documents[].revisions[].expires_onScadenza del documento.
documents[].revisions[].noteNota dell'ufficio.
documents[].revisions[].retention_policy_idLa regola di conservazione applicata.
documents[].revisions[].retention_triggerL'evento della regola da cui decorre il termine, come applicato.
documents[].revisions[].retention_trigger_onIl giorno di quell'evento.
documents[].revisions[].retention_deadlineGiorno fino al quale va conservato.
documents[].revisions[].created_atIstante di creazione.
documents[].revisions[].updated_atIstante dell'ultima modifica.
documents[].revisions[].filePercorso dell'originale nell'archivio (documents/<documento>/<revisione>.<estensione>), o null se l'originale non è disponibile.
documents[].revisions[].retention_decisionsLe decisioni dell'ufficio sulla conservazione della revisione.
documents[].revisions[].retention_decisions[].idIdentificativo della decisione.
documents[].revisions[].retention_decisions[].decisionApplicare la regola, conservare, eliminare.
documents[].revisions[].retention_decisions[].policy_beforeLa regola prima.
documents[].revisions[].retention_decisions[].policy_afterLa regola dopo.
documents[].revisions[].retention_decisions[].deadline_beforeIl termine prima.
documents[].revisions[].retention_decisions[].deadline_afterIl termine dopo.
documents[].revisions[].retention_decisions[].reasonIl motivo.
documents[].revisions[].retention_decisions[].decided_byL'account che ha deciso.
documents[].revisions[].retention_decisions[].decided_atIstante della decisione.
documents[].revisions[].retention_conflictsLe incongruenze di conservazione trovate sulla revisione, risolte comprese.
documents[].revisions[].retention_conflicts[].idIdentificativo dell'incongruenza.
documents[].revisions[].retention_conflicts[].reasonPerché: la revisione prova un requisito, il soggetto è tornato attivo, l'evento non è plausibile.
documents[].revisions[].retention_conflicts[].created_atIstante in cui è stata trovata.
documents[].revisions[].retention_conflicts[].resolved_atIstante della risoluzione.
documents[].revisions[].retention_conflicts[].decision_idLa decisione che l'ha risolta.
documents[].holdsI blocchi della cancellazione posti sul documento, tolti compresi.
documents[].holds[].idIdentificativo del blocco.
documents[].holds[].authority_refRiferimento dell'autorità o dell'atto.
documents[].holds[].placed_byL'account che l'ha posto.
documents[].holds[].placed_atIstante in cui è stato posto.
documents[].holds[].review_onGiorno in cui va rivisto.
documents[].holds[].released_byL'account che l'ha tolto.
documents[].holds[].released_atIstante in cui è stato tolto.
documents[].reviewsLe revisioni dell'ufficio sul documento, con quanto ciascuna ha affermato.
documents[].reviews[].idIdentificativo della revisione.
documents[].reviews[].revision_idLa revisione del documento esaminata.
documents[].reviews[].previous_review_idLa revisione dell'ufficio precedente.
documents[].reviews[].reviewer_idL'account che l'ha fatta.
documents[].reviews[].reviewed_atIstante della revisione.
documents[].reviews[].scopeChe cosa ha fatto: archiviazione, dati, classificazione, ritiro, ripristino.
documents[].reviews[].snapshotI dati del documento come la revisione li ha visti: un oggetto libero, nella forma che l'app usava in quel momento.
documents[].reviews[].share_with_workerSe il documento è mostrato al lavoratore nella sua app.
documents[].reviews[].claimsChe cosa la revisione ha affermato del soggetto, il giudizio di idoneità compreso.
documents[].reviews[].claims[].idIdentificativo dell'affermazione.
documents[].reviews[].claims[].worker_idIl lavoratore, se il soggetto è un lavoratore.
documents[].reviews[].claims[].employer_idL'impresa, se il soggetto è un'impresa.
documents[].reviews[].claims[].vehicle_idIl mezzo, se il soggetto è un mezzo.
documents[].reviews[].claims[].claim_kindChe cosa afferma.
documents[].reviews[].claims[].valuesI valori affermati (date, riferimenti): un oggetto libero, nella forma del tipo di affermazione.
identity_checksLe verifiche d'identità fatte dal referente sanitario dell'impresa prima che l'app del lavoratore mostri un suo documento sanitario, con il loro riferimento. Solo per le imprese di cui chi ha chiesto l'archivio legge le verifiche nell'app: tutte per un titolare, quelle di cui è referente sanitario per chi non è titolare; nessuna per chi ha un accesso in sola lettura.
identity_checks[].idIdentificativo della verifica.
identity_checks[].user_idL'account del lavoratore verificato.
identity_checks[].scopePer quali documenti: sempre i sanitari.
identity_checks[].employer_idL'impresa i cui documenti sanitari la verifica apre.
identity_checks[].custodian_idL'account che ha verificato.
identity_checks[].verified_atIstante della verifica.
identity_checks[].verification_refIl documento esibito o il riferimento della verifica.
identity_checks[].revoked_byL'account che l'ha ritirata.
identity_checks[].revoked_atIstante del ritiro.

schemas/ — archivio sanitario

I due schemi dell'archivio sanitario, manifest.schema.json e workers.schema.json, gli stessi pubblicati qui sotto /formato-esportazione/1/medical/.

documents/ — archivio sanitario

L'originale di ogni revisione disponibile dei documenti sanitari, documents/<documento>/<revisione>.<estensione>, letto dalla sua versione esatta. Fanno fede missing.originals e missing.originals_reason del manifest.

Che cosa l'archivio non contiene

  • I dati del tuo account. Il profilo, le sessioni, i consensi e le righe del registro che ti riguardano si scaricano dall'account (Account › Dati e privacy), in un file a parte che questo formato non descrive.
  • La fatturazione. L'abbonamento e le fatture si leggono e si scaricano da Impostazioni › Piano e fatturazione; il registro fiscale resta ad A176lab, che lo conserva dieci anni.
  • Le credenziali. Il codice di timbratura dei cantieri, i token dei badge e dei tablet delegati, le impronte dei codici ispettivi e degli inviti e le chiavi con cui l'app conserva i file non ci sono; le foto, i fogli inviati e gli originali, invece, ci sono, come file.
  • I dati sanitari con un esito. I giudizi di idoneità con un esito, gli esiti e i documenti sanitari escono con l'archivio sanitario.
  • Il funzionamento interno del servizio: le code, i tentativi, i contatori e la diagnostica dei messaggi (le consegne dei bot, tenute 30 giorni). La sezione seguente elenca ogni tabella che resta fuori, e perché.
  • Un'istantanea. Le famiglie di dati sono lette una dopo l'altra, a pagine: un dato registrato mentre l'archivio si scrive può comparire in un file e non in un altro. Il manifest lo dice nel campo read_mode.

Ogni tabella, dentro o fuori dall'archivio

Ogni tabella con una colonna workspace_id, e la riga dello spazio di lavoro stesso, è qui, con dove finisce nell'archivio o perché ne resta fuori. Il percorso indica il file e le chiavi sotto cui le sue righe sono annidate: sites.json/access_grants/uses sono le sessioni dentro ciascun codice ispettivo, dentro ciascun cantiere. L'elenco è quello con cui il servizio scrive l'archivio, e le sue prove falliscono se nel database compare una tabella che non vi è. members.json e consents.json leggono anche gli account collegati: il nome, l'email e il telefono dei membri, le prese visione dei lavoratori.

La colonna workspace_id delle tabelle non è ripetuta: l'archivio è di un solo spazio di lavoro. Le altre colonne ci sono tutte, tranne quelle elencate, ciascuna per uno di questi motivi: una credenziale o la sua impronta; il funzionamento interno del servizio (un contatore delle modifiche, una chiave di archiviazione, un riferimento che il servizio tiene per sé); un dato che l'archivio dice già in un altro modo (già detto: il genitore sotto cui una voce è annidata, il soggetto di un documento che le sue revisioni ripeterebbero); o una colonna che la vista dell'ufficio non mostra, perché l'archivio riporta quello che l'ufficio vede.

Ogni tabella, dentro o fuori dall'archivio
TabellaNell'archivioColonne lasciate fuori, e perché
workspaces workspace.json suspended_by, deleted_at, purged_at, purge_counts (funzionamento interno). suspended_by è l'amministratore della piattaforma che ha sospeso lo spazio; deleted_at, purged_at e purge_counts sono della cancellazione definitiva, mai valorizzati su uno spazio che esiste ancora.
document_retention_policies workspace.json/retention_policies Nessuna.
bot_workspace_settings workspace.json/bot_settings version (funzionamento interno).
memberships members.json/members Nessuna.
invitations members.json/invitations token_hash (una credenziale).
bot_workspace_links members.json/bot_links connection_id, epoch, worker_link_epoch, notice_consent_id, version (funzionamento interno). connection_id, la connessione dell'account alla chat, è nell'esportazione dell'account.
bot_notification_subscriptions members.json/bot_subscriptions connection_id, connection_proactive_epoch, version (funzionamento interno).
bot_consent_events members.json/bot_consents connection_id, instance_id (funzionamento interno).
employers employers.json version (funzionamento interno).
employer_document_policies employers.json/document_policy employer_id (già detto); version (funzionamento interno).
employer_medical_access employers.json/medical_access employer_id (già detto).
sites sites.json punch_code (una credenziale).
site_employers sites.json/employers site_id (già detto).
site_workers sites.json/assignments site_id (già detto).
gate_links sites.json/gate_links site_id (già detto); token_hash (una credenziale).
access_grants sites.json/access_grants site_id (già detto); code_hash, code_prefix (una credenziale); legacy_id, legacy_revoked (funzionamento interno). code_hash e code_prefix sono l'impronta del codice e i quattro caratteri che la indicizzano; legacy_id e legacy_revoked, la corrispondenza con il sistema precedente.
access_grant_uses sites.json/access_grants/uses grant_id (già detto); token_hash (una credenziale). L'indirizzo, mascherato, e il browser ci sono, come l'ufficio li legge nel registro degli usi.
workers workers.json photo_key, link_epoch, compliance_context_version, version (funzionamento interno). La foto è photos/<id>.jpg.
worker_compliance_facts workers.json/facts worker_id (già detto). Un giudizio di idoneità che seleziona un esito resta senza contenuto, con withheld a true; version c'è, perché la pagina del lavoratore la mostra.
worker_training_reviews workers.json/training_reviews worker_id (già detto); context_version (funzionamento interno).
worker_document_identity_checks workers.json/identity_checks worker_id (già detto); link_epoch (funzionamento interno). Per una verifica dei documenti sanitari verification_ref è null: esce con l'archivio sanitario.
badges workers.json/badge worker_id (già detto); attention_transition_id (funzionamento interno). Il token del badge sta in un'altra tabella, badge_tokens, che resta fuori.
badge_state_changes workers.json/badge_history badge_id (già detto); health_employer_id (funzionamento interno). health_employer_id dice quale regola sanitaria di quale impresa ha deciso uno stato: un riferimento che il servizio tiene per la propria lettura del verdetto, non un dato del cliente; la causa sanitaria a cui punta è tolta dai motivi.
vehicles vehicles.json plate_normalized (già detto); version (funzionamento interno). La targa come è stata scritta c'è.
documents documents.json deleted_at (già detto); medical_employer_id (nell'archivio sanitario); version (funzionamento interno). Un documento cancellato non è nell'archivio; un documento sanitario è nell'archivio sanitario.
document_revisions documents.json/revisions document_id, worker_id, employer_id, vehicle_id (già detto); upload_id, vault_key, vault_version_id, inbox_version_id, object_missing_at, version (funzionamento interno). L'originale è nella cartella documents/; un originale mancante è elencato nel manifest, in missing.
retention_decisions documents.json/revisions/retention_decisions revision_id (già detto).
retention_conflicts documents.json/revisions/retention_conflicts revision_id (già detto).
document_holds documents.json/holds document_id (già detto).
document_reviews documents.json/reviews document_id, worker_id, employer_id, vehicle_id (già detto).
document_review_claims documents.json/reviews/claims review_id, document_id (già detto). L'affermazione di un giudizio di idoneità è nell'archivio sanitario.
attendance_events attendance_events.json client_id, health_employer_id (funzionamento interno). client_id è la chiave con cui un dispositivo evita di registrare due volte la stessa timbratura; health_employer_id, lo stesso riferimento interno della storia del badge.
attendance_presence presence.json created_at, updated_at (già detto). period è scritta come starts_at, ends_at.
timesheet_sends timesheet_sends.json xlsx_key, csv_key (funzionamento interno). I file spediti sono nella cartella timesheets/.
imports imports.json file_key (funzionamento interno). Il file caricato non è nell'archivio.
import_rows imports.json/rows import_id (già detto).
audit_events audit.json ip, user_agent (non mostrata dall'ufficio); request_id (funzionamento interno). L'indirizzo e il browser delle righe che riguardano un account, e che l'account stesso ha scritto, sono nell'esportazione di quell'account.
badge_tokens Fuori: una credenziale I token che dal QR aprono la pagina pubblica del badge.
worker_medical_decisions Nell'archivio sanitario Gli esiti dei giudizi di idoneità: nell'archivio sanitario, in workers.json, sotto decisions.
billing_accounts Fuori: registri di fatturazione Il collegamento dello spazio ai sistemi di pagamento e di fatturazione elettronica, e l'email di fatturazione.
billing_invoices Fuori: registri di fatturazione Il registro delle fatture e delle note di credito: le fatture si scaricano da Impostazioni › Piano e fatturazione, e il registro resta ad A176lab per dieci anni.
subscriptions Fuori: registri di fatturazione L'abbonamento al piano: si legge da Impostazioni › Piano e fatturazione.
billing_checkouts Fuori: funzionamento interno Gli acquisti in corso sulla pagina di pagamento, che scadono.
workspace_exports Fuori: funzionamento interno Le richieste di esportazione stesse, con il loro stato.
deletion_requests Fuori: funzionamento interno Le richieste di cancellazione e il loro avanzamento.
erasure_intents Fuori: funzionamento interno I lavori che eseguono una cancellazione, un passo alla volta.
document_deletions Fuori: funzionamento interno I lavori che cancellano un documento o una revisione dall'archivio dei file.
document_processing_attempts Fuori: funzionamento interno I tentativi di controllo e di copia di un file caricato.
document_uploads Fuori: funzionamento interno Le prenotazioni di un caricamento, prima che il file diventi una revisione.
document_usage Fuori: funzionamento interno Il contatore dello spazio occupato dai documenti.
bot_command_admissions Fuori: funzionamento interno L'ammissione dei comandi ricevuti in chat, con le loro scadenze.
bot_deliveries Fuori: funzionamento interno La diagnostica delle consegne dei messaggi dei bot, tenuta 30 giorni: code, tentativi e chiavi del fornitore, mai il testo di un messaggio.
bot_delivery_sources Fuori: funzionamento interno Il legame tra una consegna e ciò che l'ha causata.
bot_intents Fuori: funzionamento interno I passaggi da una chat al wallet per completare una timbratura.
bot_interactions Fuori: funzionamento interno Le interazioni in corso con il bot, che scadono.
bot_legacy_links Fuori: funzionamento interno La corrispondenza con i collegamenti del sistema precedente.
bot_media_cleanup Fuori: funzionamento interno I file temporanei dei bot da cancellare.
bot_notification_sources Fuori: funzionamento interno La coda degli eventi che possono generare un avviso.

Gli schemi JSON

Ogni file JSON dei due archivi ha uno schema JSON, draft 2020-12, scritto a mano e pubblicato qui all'indirizzo che il suo $id dichiara: ogni campo è descritto, e un campo che lo schema non nomina è rifiutato (additionalProperties: false), salvo negli oggetti che lo schema dice liberi, come le istantanee del registro delle attività. Le prove del servizio costruiscono gli archivi di uno spazio di lavoro di prova e li validano contro questi schemi; ogni archivio ne porta una copia nella cartella schemas/.

L'archivio dello spazio di lavoro

L'archivio sanitario

Giurisdizione e accesso ai dati

L'articolo 28 del Regolamento (UE) 2023/2854 chiede a chi fornisce servizi di trattamento dei dati di indicare sul proprio sito la giurisdizione a cui è soggetta l'infrastruttura con cui li tratta, e di descrivere le misure tecniche, organizzative e contrattuali che adotta per impedire l'accesso ai dati non personali conservati nell'Unione, o il loro trasferimento, da parte di autorità di paesi terzi, quando sarebbe in contrasto con il diritto dell'Unione o con quello dello Stato membro interessato.

CantiereGo è fornito da A176lab S.r.l., una società con sede in Italia, ad Alcamo (TP), e i Termini di servizio sono regolati dalla legge italiana. L'infrastruttura che conserva i dati dei clienti è nella regione AWS di Milano (eu-south-1), in Italia: il server dell'app e il suo database, gli archivi dei file e dei documenti, le copie di sicurezza e le istantanee del disco dei dati, i registri tecnici. Dalla stessa regione partono le email e gli SMS. Nessuno di questi dati è replicato in un'altra regione.

Le pagine del sito e dell'app arrivano ai browser attraverso CloudFront, la rete di distribuzione di AWS, dai punti di presenza della classe di prezzo scelta, in Europa, Israele, Turchia, Stati Uniti, Messico e Canada; AWS avverte che di tanto in tanto un contenuto può essere servito da un punto di presenza che non fa parte di quella classe. Un punto di presenza termina la connessione cifrata e non conserva le risposte dell'app che portano i dati dei clienti, che arrivano dal server di Milano (sezione 7 dell'Informativa sulla privacy).

Gli altri fornitori che trattano dati per il servizio comprendono quelli che le sezioni 6 e 7 dell'Informativa sulla privacy elencano con il luogo in cui li trattano — Sentry, per le segnalazioni di errore, e Zoho Mail, per la casella info@cantierego.it, li conservano nell'Unione europea; Stripe, per i pagamenti, li tratta in Irlanda e può trasferirli alle società del proprio gruppo negli Stati Uniti — e Fatture in Cloud (TeamSystem S.p.A., Italia), con cui A176lab emette e trasmette le fatture elettroniche ai propri clienti, che conserva i dati nell'Unione europea. Il cliente può inoltre abilitare per il proprio spazio di lavoro i canali Telegram e, dal piano Professional, WhatsApp: i messaggi scambiati con il bot sono trattati dai fornitori di quei canali, Telegram e, per WhatsApp, Meta, secondo i propri termini.

Misure tecniche

  • Cifratura a riposo: i dischi del server, compreso quello del database, sono cifrati; gli archivi dei file dell'app e dei documenti sono cifrati con la chiave di S3 gestita da AWS in AWS KMS, gli altri archivi, compreso quello delle copie di sicurezza, con la cifratura lato server di S3.
  • Cifratura in transito: i browser raggiungono app.cantierego.it e cantierego.it soltanto con TLS 1.3; il tratto tra CloudFront e il server è cifrato con almeno TLS 1.2 (in TLS 1.2 con i soli cifrari ECDHE e AES-GCM); gli archivi rifiutano ogni richiesta che non arrivi cifrata.
  • Accesso all'infrastruttura: il server non conserva chiavi di accesso ad AWS, perché firma ogni sua chiamata con il ruolo dell'istanza, i cui permessi sono limitati agli archivi e ai servizi che il server usa; accetta connessioni web soltanto da CloudFront, che porta un segreto che il server verifica, e non ha una porta SSH aperta su internet.

Misure organizzative

  • In A176lab accedono ai dati soltanto le persone autorizzate, vincolate alla riservatezza e solo per quanto serve al servizio (articolo 6.5 dei Termini di servizio).
  • Le persone di A176lab accedono all'account AWS con AWS IAM Identity Center, con il secondo fattore a ogni accesso, e al server attraverso una rete privata cifrata, che chiede di nuovo l'identità a intervalli regolari, o, in emergenza, attraverso AWS stesso.
  • Un amministratore della piattaforma agisce soltanto da una sessione verificata con il secondo fattore, che dura al più ventiquattro ore, e ogni sua modifica è tracciata nel registro delle attività.
  • Le operazioni di gestione dell'account AWS sono registrate da AWS CloudTrail, in ogni regione, con la verifica dell'integrità dei registri.

Misure contrattuali

  • Sui dati personali che il Cliente registra, A176lab è responsabile del trattamento e li tratta soltanto su istruzione documentata del Cliente, salvo che lo richieda il diritto dell'Unione o nazionale a cui A176lab è soggetta; in tal caso informa il Cliente di tale obbligo giuridico prima del trattamento, a meno che il diritto vieti tale informazione per rilevanti motivi di interesse pubblico (articolo 6.4 dei Termini di servizio).
  • Presso A176lab e i fornitori elencati nella sezione 6 dell'Informativa sulla privacy, i dati non sono trasferiti fuori dall'Unione europea, salvo quanto descritto nella sezione 7 dell'Informativa sulla privacy (articolo 6.4 dei Termini), che ne indica le basi: per il passaggio da CloudFront, l'accordo sul trattamento dei dati di AWS e le clausole contrattuali standard approvate dalla Commissione europea; per Stripe, la decisione di adeguatezza per il Data Privacy Framework UE-USA, a cui Stripe, Inc. aderisce, e le clausole contrattuali standard. Questo impegno non riguarda i messaggi delle chat con i bot Telegram e WhatsApp: il server di A176lab li scambia con Telegram e, attraverso AWS, con Meta, che li trattano secondo i propri termini.
  • Ogni fornitore elencato nella sezione 6 dell'Informativa è vincolato da un accordo sul trattamento dei dati; A176lab impone ai sub-responsabili obblighi di protezione dei dati equivalenti a quelli dell'articolo 6 dei Termini, ne risponde verso il Cliente e gli comunica in anticipo l'aggiunta o la sostituzione di un sub-responsabile, a cui il Cliente può opporsi (articolo 6.7).

Il dettaglio è nei testi legali: