{
  "openapi": "3.0.3",
  "info": {
    "title": "DPAC T2 Packager · API locale",
    "version": "0.1.0",
    "description": "API HTTP esposta dall'app DPAC T2 Packager sul PC (solo loopback). Permette a un sistema esterno (per esempio il nodo GPU AerariumChain o il gestionale di un fornitore) di creare, verificare e zippare pacchetti T2 della Digital Library con lo stesso codice della UI. Flusso tipico: POST /build → GET /jobs/{id} (o SSE /jobs/{id}/events) → risultato con rapporto di verifica e certificato PDF."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:47821/api/v1"
    }
  ],
  "security": [
    {
      "apiToken": []
    },
    {
      "bearer": []
    },
    {}
  ],
  "tags": [
    {
      "name": "sistema"
    },
    {
      "name": "pacchetti T2"
    },
    {
      "name": "job"
    },
    {
      "name": "documenti"
    },
    {
      "name": "registro"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "sistema"
        ],
        "summary": "Stato dell'app",
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "app": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "time": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "sistema"
        ],
        "summary": "Questo documento",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.0"
          }
        }
      }
    },
    "/artec/status": {
      "get": {
        "tags": [
          "sistema"
        ],
        "summary": "Stato della CLI aec_artecViewer (export RAW_3D dai progetti Artec)",
        "description": "Dove è cli.js, quale Node la esegue (serve Node >= 22.15 con zstd integrato) e la versione dello strumento. Con ok=false il messaggio dice cosa manca.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "status": {
                      "$ref": "#/components/schemas/ArtecCliStatus"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/artec/list": {
      "post": {
        "tags": [
          "sistema"
        ],
        "summary": "Elenca gli oggetti di un progetto Artec (scansioni, frame, foto)",
        "description": "Esegue aec_artecViewer --list sulla cartella del progetto: per ogni scansione il numero di frame e di foto che l'export produrrà.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectPath"
                ],
                "properties": {
                  "projectPath": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "projectDir": {
                      "type": "string"
                    },
                    "objects": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ArtecListEntry"
                      }
                    },
                    "status": {
                      "$ref": "#/components/schemas/ArtecCliStatus"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/disks": {
      "get": {
        "tags": [
          "sistema"
        ],
        "summary": "Volumi montati e spazio libero",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "volumes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "free": {
                            "type": "integer",
                            "nullable": true
                          },
                          "total": {
                            "type": "integer",
                            "nullable": true
                          },
                          "external": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/build": {
      "post": {
        "tags": [
          "pacchetti T2"
        ],
        "summary": "Crea un pacchetto T2 (job)",
        "description": "Costruisce il pacchetto in output.dir/<CANTIERE_LOTTO_PK_T2>/: METS T2 (UPDATE_3D, UUID DPAC), paradati, RAW_3D (file, .acraw o formato originale), verifica, ZIP, certificato. Tutti i percorsi sono locali al PC dove gira l'app.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuildSpec"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job avviato",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "jobId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/check": {
      "post": {
        "tags": [
          "pacchetti T2"
        ],
        "summary": "Verifica un pacchetto (cartella o ZIP)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target"
                ],
                "properties": {
                  "target": {
                    "type": "string",
                    "description": "cartella del pacchetto o file ZIP"
                  },
                  "t1Path": {
                    "type": "string",
                    "description": "METS T1 per il confronto delta"
                  },
                  "expectedUuid": {
                    "type": "string"
                  },
                  "remoteValidator": {
                    "type": "boolean",
                    "description": "invia il METS anche al validatore pubblico ICDP"
                  },
                  "skipHashes": {
                    "type": "boolean"
                  },
                  "wait": {
                    "type": "boolean",
                    "description": "true = risposta sincrona con il rapporto"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rapporto (wait=true)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "report": {
                      "$ref": "#/components/schemas/CheckReport"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Job avviato",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "jobId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/zip": {
      "post": {
        "tags": [
          "pacchetti T2"
        ],
        "summary": "Verifica e zippa una cartella di pacchetto (job)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "stagingDir"
                ],
                "properties": {
                  "stagingDir": {
                    "type": "string"
                  },
                  "outDir": {
                    "type": "string"
                  },
                  "force": {
                    "type": "boolean",
                    "description": "zippa anche con errori"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job avviato",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "jobId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/acraw": {
      "post": {
        "tags": [
          "pacchetti T2"
        ],
        "summary": "Crea un contenitore .acraw da file grezzi (job)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "files",
                  "outPath"
                ],
                "properties": {
                  "files": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "outPath": {
                    "type": "string"
                  },
                  "objid": {
                    "type": "string"
                  },
                  "options": {
                    "$ref": "#/components/schemas/AcrawOptions"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job avviato",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "jobId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/pdf/setup": {
      "post": {
        "tags": [
          "documenti"
        ],
        "summary": "Genera la Relazione di Setup / Scheda di rilievo (PDF)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "outPath"
                ],
                "properties": {
                  "data": {
                    "$ref": "#/components/schemas/SchedaData"
                  },
                  "outPath": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "outPath": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/pdf/elaborazione": {
      "post": {
        "tags": [
          "documenti"
        ],
        "summary": "Genera la Relazione di elaborazione (PDF) dal METS T1",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "t1Path",
                  "outPath"
                ],
                "properties": {
                  "t1Path": {
                    "type": "string"
                  },
                  "data": {
                    "$ref": "#/components/schemas/ElaborazioneData"
                  },
                  "outPath": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "outPath": {
                      "type": "string"
                    },
                    "values": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs": {
      "get": {
        "tags": [
          "job"
        ],
        "summary": "Elenco job",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "jobs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Job"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}": {
      "get": {
        "tags": [
          "job"
        ],
        "summary": "Stato, risultato ed eventi di un job",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "job": {
                      "$ref": "#/components/schemas/Job"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/JobEvent"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}/events": {
      "get": {
        "tags": [
          "job"
        ],
        "summary": "Eventi del job in Server-Sent Events",
        "description": "Replay degli eventi passati e poi in tempo reale: `event: progress|done|error`, `data: JSON`. Si chiude dopo done/error.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "text/event-stream"
          },
          "404": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/packages": {
      "get": {
        "tags": [
          "registro"
        ],
        "summary": "Pacchetti verificati (generati / falliti)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "packages": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PackageRecord"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/packages/{id}": {
      "get": {
        "tags": [
          "registro"
        ],
        "summary": "Un pacchetto con il rapporto completo",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "package": {
                      "$ref": "#/components/schemas/PackageRecord"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Errore",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "registro"
        ],
        "summary": "Rimuove dal registro",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Token",
        "description": "token impostato nelle Impostazioni dell'app (vuoto = nessuna autenticazione)"
      },
      "bearer": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "string"
          }
        }
      },
      "BuildSpec": {
        "type": "object",
        "required": [
          "identity",
          "t1",
          "paradata",
          "raw",
          "output"
        ],
        "properties": {
          "identity": {
            "type": "object",
            "required": [
              "objid"
            ],
            "properties": {
              "codiceCantiere": {
                "type": "string",
                "example": "3D03CE05"
              },
              "codiceLotto": {
                "type": "string",
                "example": "LDIG003"
              },
              "pk": {
                "type": "string",
                "example": "PK0000002"
              },
              "objid": {
                "type": "string",
                "description": "prefisso del pacchetto: <objid>.xml, <objid>_PARADATA_3D/, <objid>_RAW_3D/"
              },
              "dpacUuid": {
                "type": "string",
                "format": "uuid",
                "description": "UUID della risorsa assegnato da DPAC dopo il T1 → metsHdr@ID del T2"
              },
              "recordStatus": {
                "type": "string",
                "default": "UPDATE_3D"
              },
              "title": {
                "type": "string"
              },
              "inventory": {
                "type": "string"
              },
              "catalogId": {
                "type": "string"
              }
            }
          },
          "t1": {
            "type": "object",
            "required": [
              "source"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "file",
                  "url"
                ]
              },
              "path": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "headers": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "packagePath": {
                "type": "string",
                "description": "pacchetto T1 (cartella o ZIP) da cui copiare nel T2 i file del T1 scelti con options.includeT1Files"
              },
              "packageS3Key": {
                "type": "string",
                "description": "in alternativa: chiave S3 del pacchetto T1 sull'hub (richiede il login); vengono lette solo le voci necessarie, a intervalli di byte"
              }
            },
            "description": "METS T1 ingerito (il T2 è un delta su di esso)"
          },
          "paradata": {
            "type": "object",
            "required": [
              "setup",
              "elaborazione"
            ],
            "properties": {
              "setup": {
                "$ref": "#/components/schemas/ParadataDoc"
              },
              "elaborazione": {
                "$ref": "#/components/schemas/ParadataDoc"
              },
              "extraFiles": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "raw": {
            "type": "object",
            "required": [
              "mode"
            ],
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "files",
                  "folder",
                  "original",
                  "artec",
                  "none"
                ],
                "description": "files/folder = file grezzi sciolti (PLY…); original = progetto nel formato nativo del software (cartella zippata senza ricompressione o archivio copiato); artec = export dal progetto Artec Studio con la CLI aec_artecViewer (una PLY grezza per scansione + le foto delle scansioni come PNG), lo stesso strumento e gli stessi filtri del nodo GPU; none = segnaposto RAW_3D"
              },
              "artec": {
                "$ref": "#/components/schemas/ArtecExportOptions"
              },
              "files": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "folder": {
                "type": "string"
              },
              "extensions": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "default": [
                  "ply"
                ]
              },
              "keepNames": {
                "type": "boolean",
                "default": false
              },
              "originalPath": {
                "type": "string"
              },
              "originalVendor": {
                "type": "string",
                "example": "artec"
              },
              "acraw": {
                "$ref": "#/components/schemas/AcrawOptions"
              }
            }
          },
          "options": {
            "type": "object",
            "properties": {
              "includeT1Files": {
                "type": "string",
                "enum": [
                  "images",
                  "all",
                  "none"
                ],
                "default": "images",
                "description": "quali file del T1 rimettere nel T2: images = thumbnail e render (fileGrp PREVIEW/LOW), all = tutti, none = solo riferimenti (delta puro). Copiati byte per byte dal pacchetto T1 e verificati con SIZE/CHECKSUM del METS"
              },
              "stripViewImages": {
                "type": "boolean"
              },
              "zipLevel": {
                "type": "integer"
              },
              "overwrite": {
                "type": "boolean",
                "description": "svuota la cartella di lavoro se esiste"
              }
            }
          },
          "output": {
            "type": "object",
            "required": [
              "dir"
            ],
            "properties": {
              "dir": {
                "type": "string",
                "description": "cartella di destinazione (disco esterno)"
              },
              "zip": {
                "type": "boolean",
                "default": true
              },
              "keepStaging": {
                "type": "boolean",
                "default": true
              },
              "forceZip": {
                "type": "boolean",
                "default": false
              }
            }
          }
        }
      },
      "BuildResult": {
        "type": "object",
        "properties": {
          "zipStem": {
            "type": "string"
          },
          "packageDir": {
            "type": "string",
            "description": "<output.dir>/<stem>: ZIP di consegna, certificato, ZIP di verifica e, con keepStaging, le cartelle non zippate <stem>/ e <stem>_VERIFICA/"
          },
          "t1Files": {
            "type": "object",
            "properties": {
              "scope": {
                "type": "string"
              },
              "included": {
                "type": "integer"
              },
              "missing": {
                "type": "integer"
              },
              "mismatched": {
                "type": "integer"
              },
              "bytes": {
                "type": "integer"
              },
              "source": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "stagingDir": {
            "type": "string"
          },
          "metsPath": {
            "type": "string"
          },
          "zipPath": {
            "type": "string",
            "nullable": true
          },
          "zipSize": {
            "type": "integer",
            "nullable": true
          },
          "zipMd5": {
            "type": "string",
            "nullable": true
          },
          "storageFiles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "size": {
                  "type": "integer"
                },
                "md5": {
                  "type": "string"
                }
              }
            }
          },
          "rawFiles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "size": {
                  "type": "integer"
                },
                "md5": {
                  "type": "string"
                }
              }
            }
          },
          "acrawPath": {
            "type": "string",
            "nullable": true
          },
          "rawPhotos": {
            "type": "integer",
            "description": "immagini di input (foto delle scansioni) in RAW_3D"
          },
          "artec": {
            "type": "object",
            "nullable": true,
            "description": "esecuzione di aec_artecViewer (raw.mode = artec): tool, toolVersion, kind, scanGeometry, files, photos, sizeTarget, cli, durationMs"
          },
          "check": {
            "$ref": "#/components/schemas/CheckReport"
          },
          "buildRecordPath": {
            "type": "string"
          },
          "certificatePath": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ParadataDoc": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "generate",
              "file",
              "none"
            ]
          },
          "path": {
            "type": "string",
            "description": "PDF esistente (mode=file)"
          },
          "data": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SchedaData"
              },
              {
                "$ref": "#/components/schemas/ElaborazioneData"
              }
            ]
          }
        }
      },
      "SchedaData": {
        "type": "object",
        "description": "Campi della Relazione di Setup / Scheda di rilievo (modello MiC). Tutti opzionali, testo libero.",
        "properties": {
          "id_oggetto": {
            "type": "string"
          },
          "indice_complessita": {
            "type": "string"
          },
          "note_oggetto": {
            "type": "string"
          },
          "setup_acquisizione": {
            "type": "string"
          },
          "trattamento": {
            "type": "string"
          },
          "note_set": {
            "type": "string"
          },
          "modalita_strumenti": {
            "type": "string"
          },
          "condizioni_ambientali": {
            "type": "string"
          },
          "numero_acquisizioni": {
            "type": "string"
          },
          "posizioni_acquisizione": {
            "type": "string"
          },
          "parametri_immagini": {
            "type": "string"
          },
          "parametri_geometria": {
            "type": "string"
          },
          "registrazione_campo": {
            "type": "string"
          },
          "elaborazione_campo": {
            "type": "string"
          },
          "software": {
            "type": "string"
          },
          "note_acq": {
            "type": "string"
          },
          "preparazione_set": {
            "type": "string"
          },
          "tempo_acquisizione": {
            "type": "string"
          },
          "tempo_elaborazione": {
            "type": "string"
          },
          "note_tempi": {
            "type": "string"
          },
          "tipo_ambiente": {
            "type": "string"
          },
          "delimitazione_spazio": {
            "type": "string"
          },
          "illuminazione": {
            "type": "string"
          },
          "strumentazione": {
            "type": "string"
          },
          "link_scheda_tecnica": {
            "type": "string"
          },
          "certificato_calibrazione": {
            "type": "string"
          },
          "sistemi_riferimento": {
            "type": "string"
          },
          "tipologia_target": {
            "type": "string"
          },
          "strumenti_supporto": {
            "type": "string"
          },
          "software_acquisizione": {
            "type": "string"
          },
          "foto_link": {
            "type": "string"
          }
        }
      },
      "ElaborazioneData": {
        "type": "object",
        "description": "Dati della Relazione di elaborazione; i blocchi MASTER/DERIVATO sono letti dal METS T1, questi campi li completano.",
        "properties": {
          "operator": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "inventory": {
            "type": "string"
          },
          "catalogId": {
            "type": "string"
          },
          "derivFile": {
            "type": "string",
            "example": "X_DRV.glb"
          },
          "derivSize": {
            "type": "string",
            "example": "3.11 MB"
          },
          "derivSoftware": {
            "type": "string",
            "example": "Blender"
          },
          "derivDate": {
            "type": "string",
            "example": "2026-10-08"
          },
          "derivFormat": {
            "type": "string"
          },
          "overrides": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "valori per chiave di campo (m_*, d_*, o_*)"
          }
        }
      },
      "AcrawOptions": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "profile": {
            "type": "string",
            "enum": [
              "full",
              "distribution"
            ]
          },
          "captureKind": {
            "type": "string",
            "enum": [
              "point_cloud",
              "range_grid",
              "tls_scan",
              "image",
              "line_profile"
            ]
          },
          "units": {
            "type": "string",
            "enum": [
              "mm",
              "m"
            ]
          },
          "upAxis": {
            "type": "string",
            "enum": [
              "+Y",
              "+Z"
            ]
          },
          "vendorId": {
            "type": "string",
            "description": "id vendor della cartella L0 (REGISTRY.md della spec)"
          },
          "l0Folder": {
            "type": "string",
            "description": "cartella del progetto vendor copiata byte per byte in L0 (profile=full)"
          },
          "sensor": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string"
              },
              "make": {
                "type": "string"
              },
              "model": {
                "type": "string"
              },
              "serial": {
                "type": "string"
              },
              "firmware": {
                "type": "string"
              }
            }
          },
          "provenance": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "holder": {
                "type": "string"
              },
              "organization": {
                "type": "string"
              },
              "operator": {
                "type": "string"
              },
              "location": {
                "type": "string"
              },
              "start": {
                "type": "string"
              },
              "end": {
                "type": "string"
              },
              "software": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string"
                    }
                  }
                }
              },
              "rightsHolder": {
                "type": "string"
              },
              "license": {
                "type": "string"
              }
            }
          }
        }
      },
      "ArtecExportOptions": {
        "type": "object",
        "description": "Opzioni dell'export aec_artecViewer (raw.mode = artec). Rispettano i filtri della CLI: kind sceglie gli oggetti, scanGeometry la geometria (raw = ogni frame come registrato), targetTotal fa stare l'export in un budget scegliendo HD/SD per scansione senza mai scartare frame, maxSize/onOversize/maxTotalSize sono i limiti di dimensione. Un file fuso o incompleto fa fallire l'export (gate di provenienza del server DPAC).",
        "properties": {
          "projectPath": {
            "type": "string",
            "description": "cartella del progetto Artec (con il file .a3d e data/) oppure ZIP della cartella"
          },
          "projectS3Key": {
            "type": "string",
            "description": "in alternativa a projectPath: chiave S3 del progetto registrato sull'hub (richiede il login), scaricato prima dell'export"
          },
          "kind": {
            "type": "string",
            "enum": [
              "scan",
              "fused",
              "all"
            ],
            "default": "scan"
          },
          "scanGeometry": {
            "type": "string",
            "enum": [
              "raw",
              "fused"
            ],
            "default": "raw"
          },
          "fuseCell": {
            "type": "number",
            "description": "mm, solo scanGeometry=fused"
          },
          "targetTotal": {
            "type": "string",
            "example": "5GB"
          },
          "maxSize": {
            "type": "string",
            "example": "2GB",
            "description": "limite per file, \"off\" per disattivarlo"
          },
          "onOversize": {
            "type": "string",
            "enum": [
              "refuse",
              "reduce"
            ]
          },
          "maxTotalSize": {
            "type": "string",
            "example": "8GB"
          },
          "maxVerts": {
            "type": "integer"
          },
          "photos": {
            "type": "boolean",
            "default": true,
            "description": "esporta anche le foto della camera texture di ogni scansione (PNG lossless, <prefisso>_RAW_NN_INP_NNNN.png) elencate nel METS come immagini di input"
          }
        }
      },
      "ArtecCliStatus": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "cliPath": {
            "type": "string",
            "nullable": true
          },
          "cliDir": {
            "type": "string",
            "nullable": true
          },
          "nodeBin": {
            "type": "string",
            "nullable": true
          },
          "nodeVersion": {
            "type": "string",
            "nullable": true
          },
          "zstd": {
            "type": "boolean",
            "nullable": true
          },
          "toolVersion": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ArtecListEntry": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "scan",
              "fused",
              "frame"
            ]
          },
          "vertices": {
            "type": "integer"
          },
          "state": {
            "type": "string"
          },
          "frames": {
            "type": "integer",
            "nullable": true
          },
          "photos": {
            "type": "integer",
            "nullable": true
          }
        }
      },
      "CheckReport": {
        "type": "object",
        "required": [
          "ok",
          "errors",
          "warnings",
          "items",
          "summary"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "true = nessun errore (gli avvisi non bloccano)"
          },
          "errors": {
            "type": "integer"
          },
          "warnings": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CheckItem"
            }
          },
          "summary": {
            "$ref": "#/components/schemas/CheckSummary"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "durationMs": {
            "type": "integer"
          },
          "certificatePath": {
            "type": "string",
            "nullable": true,
            "description": "PDF del certificato di verifica, scritto fuori dal pacchetto quando la verifica è superata"
          }
        }
      },
      "CheckItem": {
        "type": "object",
        "required": [
          "id",
          "level",
          "message"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Id stabile della regola (HDR-ID, FSEC-STORAGE, FILE-MD5, …)"
          },
          "level": {
            "type": "string",
            "enum": [
              "error",
              "warn",
              "info",
              "ok"
            ]
          },
          "message": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "file": {
            "type": "string",
            "description": "percorso relativo al pacchetto"
          }
        }
      },
      "CheckSummary": {
        "type": "object",
        "properties": {
          "packageDir": {
            "type": "string"
          },
          "metsFile": {
            "type": "string",
            "nullable": true
          },
          "objid": {
            "type": "string",
            "nullable": true
          },
          "metsHdrId": {
            "type": "string",
            "nullable": true
          },
          "recordStatus": {
            "type": "string",
            "nullable": true
          },
          "profile": {
            "type": "string",
            "nullable": true
          },
          "packageKind": {
            "type": "string",
            "enum": [
              "T2",
              "T1-3D",
              "T1-GIGAPIXEL",
              "UNKNOWN"
            ]
          },
          "storageFiles": {
            "type": "integer"
          },
          "rawFiles": {
            "type": "integer"
          },
          "rawImages": {
            "type": "integer"
          },
          "t1Files": {
            "type": "integer",
            "description": "file del T1 presenti nel pacchetto e verificati"
          },
          "totalBytes": {
            "type": "integer"
          },
          "fileCount": {
            "type": "integer"
          },
          "zip64Needed": {
            "type": "boolean"
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "size": {
                  "type": "integer"
                },
                "md5": {
                  "type": "string",
                  "nullable": true
                },
                "group": {
                  "type": "string"
                }
              }
            }
          },
          "remoteValidator": {
            "type": "object",
            "nullable": true,
            "properties": {
              "called": {
                "type": "boolean"
              },
              "esito": {
                "type": "boolean",
                "nullable": true
              },
              "httpStatus": {
                "type": "integer",
                "nullable": true
              },
              "messages": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Job": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "build",
              "check",
              "zip",
              "acraw",
              "extract"
            ]
          },
          "label": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "done",
              "failed"
            ]
          },
          "startedAt": {
            "type": "integer"
          },
          "finishedAt": {
            "type": "integer",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "result": {
            "description": "BuildResult (build), { report, record } (check), { zipPath, size, md5, report, certificatePath } (zip)",
            "nullable": true
          },
          "lastEvent": {
            "$ref": "#/components/schemas/JobEvent",
            "nullable": true
          }
        }
      },
      "JobEvent": {
        "type": "object",
        "properties": {
          "ts": {
            "type": "integer"
          },
          "event": {
            "type": "string",
            "enum": [
              "progress",
              "done",
              "error",
              "log"
            ]
          },
          "data": {
            "description": "progress: { step, percent, message } · done: risultato · error: { error }"
          }
        }
      },
      "PackageRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "built",
              "checked"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "checkedAt": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "errors": {
            "type": "integer"
          },
          "warnings": {
            "type": "integer"
          },
          "problems": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "file": {
                  "type": "string"
                }
              }
            }
          },
          "objid": {
            "type": "string",
            "nullable": true
          },
          "metsHdrId": {
            "type": "string",
            "nullable": true
          },
          "recordStatus": {
            "type": "string",
            "nullable": true
          },
          "totalBytes": {
            "type": "integer"
          },
          "zipPath": {
            "type": "string",
            "nullable": true
          },
          "stagingDir": {
            "type": "string",
            "nullable": true
          },
          "certificatePath": {
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}