<?xml version="1.0" encoding="UTF-8"?>
<!--
  Schema XML del informe de verificación de integridad sellado v2.
  Namespace: https://docs.docuten.com/earchiving/integrity-report/v2
  Decisión: D-06 (Phase 06.7) — el informe sellado lleva el MOTIVO de su veredicto en un vocabulario
  CERRADO; D-15 (Phase 05.1) — se sella con el MISMO pipeline QTSP+TSA que la atestación de origen.

  POR QUÉ EXISTE UN v2

  integrity-report-v1.xsd NO lleva el motivo del veredicto: un informe sellado que dice «FAIL» sin
  decir por qué no es legible para un tercero (DI-06.2-11-A). Los documentos v1 ya sellados son
  INMUTABLES, así que el motivo no se añade a v1: un cambio de formato sellado es siempre una versión
  nueva. v1 sigue vigente para todo lo ya sellado y sigue siendo legible; los informes NUEVOS se
  emiten en v2. Este esquema hace opcional el elemento «reason» y deja a cargo del emisor
  (IntegrityReportInput) exigirlo para todo veredicto que no sea PASS.

  QUÉ CERTIFICA ESTE DOCUMENTO

  El RESULTADO de una comprobación puntual de integridad: qué AIP se comprobó, cuándo, qué Merkle
  root se recomputó desde el blob WORM, contra qué root sellado se contrastó, cuál fue el veredicto
  y, salvo en PASS, por qué. Sellado por el QTSP y con token TSA RFC 3161, de modo que el resultado
  de la comprobación es en sí mismo evidencia cualificada y no un simple registro de aplicación.

  QUÉ *NO* ES

  NO es la atestación de origen (origin-attestation.xml, attestation-v1.xsd, sello #1), que
  acredita la autenticidad de ORIGEN del SIP.
  NO es el sidecar de fixity del AIP completo (aip-hash-attestation-v1.xsd / -v2.xsd, sello #2,
  D-26), que es la EVIDENCIA contra la que se compara. Este documento certifica el resultado de
  COMPARAR contra esa evidencia — son dos hechos distintos con dos artefactos distintos.
  Por eso este esquema no importa, no extiende y no comparte ObjectFactory con ninguno de los
  otros dos ni con integrity-report-v1.xsd: sus bindings van a un paquete propio.

  LOS CUATRO VEREDICTOS SON DISJUNTOS

  result admite exactamente PASS, FAIL, NOT_ANCHORABLE y ERROR, y ninguno más. Los estados de
  ciclo de vida del contrato asíncrono (PENDING/RUNNING) NO son veredictos y quedan fuera de la
  enumeración a propósito: un informe cualificado que sellase «todavía no sé nada» certificaría
  una no-respuesta como si fuera un hecho comprobado.

  recomputedRoot y sealedRoot son opcionales porque NOT_ANCHORABLE (AIP nunca anclado, D-16/D-17)
  y ERROR (comprobación interrumpida) pueden no tener ninguno de los dos. Rellenarlos con un
  valor de relleno sería peor que dejarlos ausentes: un root inventado dentro de un documento
  sellado es evidencia falsa.

  Bindings JAXB: integrity-report-v2.xjb
                 → paquete com.docuten.earchiving.attestation.internal.generated.integrityreportv2
-->
<xs:schema
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ir="https://docs.docuten.com/earchiving/integrity-report/v2"
    targetNamespace="https://docs.docuten.com/earchiving/integrity-report/v2"
    elementFormDefault="qualified"
    version="2.0">

  <!-- Elemento raíz: ir:integrityReport -->
  <xs:element name="integrityReport" type="ir:IntegrityReportType"/>

  <xs:complexType name="IntegrityReportType">
    <xs:sequence>
      <!-- AIP cuya integridad se comprobó -->
      <xs:element name="aipId" type="xs:string"/>
      <!-- Tenant propietario del AIP (multi-tenant) -->
      <xs:element name="tenantId" type="xs:string"/>
      <!--
        Identificador de la comprobación (aip_integrity_checks.id): el MISMO valor que el cliente
        recibió en el 202 Accepted y que enlaza este informe con la fila del historial, el evento
        PREMIS de fixity y la entrada del audit log hash-chained (D-12).
      -->
      <xs:element name="checkId" type="xs:string"/>
      <!-- Instante UTC de la comprobación (la «fecha» del criterio de éxito 5 de la fase) -->
      <xs:element name="checkedAt" type="xs:dateTime"/>
      <!--
        Merkle root SHA-256 hex recomputado desde el blob WORM real, AIP completo sin exclusiones
        (D-26). Ausente cuando el veredicto no permitió calcularlo.
      -->
      <xs:element name="recomputedRoot" type="xs:string" minOccurs="0"/>
      <!--
        Merkle root SHA-256 hex leído del sidecar sellado de sello #2 — la referencia con fuerza
        probatoria. Ausente cuando no se llegó a leer.
      -->
      <xs:element name="sealedRoot" type="xs:string" minOccurs="0"/>
      <!--
        URI versionada estable del perfil Merkle bajo el que se recomputó recomputedRoot
        (GATE-02, Phase 05.1.2 — D-26 aplicado por analogía al informe de verificación).

        Opcional, igual que en v1. Se puebla SI Y SOLO SI el informe declara recomputedRoot, con
        INDEPENDENCIA del veredicto final; queda AUSENTE únicamente cuando recomputedRoot en sí es
        null: declarar el perfil de un cálculo que no ocurrió sería, como un root de relleno,
        evidencia falsa dentro de un documento sellado.

        Describe LA RECOMPUTACIÓN de este servicio, no el perfil del root sellado — ése lo declara
        el propio sidecar de sello #2 si es v2, y es desconocido si es v1.
      -->
      <xs:element name="merkleProfile" type="xs:string" minOccurs="0"/>
      <!-- Veredicto de la comprobación -->
      <xs:element name="result" type="ir:ResultType"/>
      <!--
        Motivo del veredicto (D-06): vocabulario CERRADO, ausente en PASS (un PASS no tiene nada
        que explicar). El emisor lo exige para FAIL, ERROR y NOT_ANCHORABLE; el esquema lo deja
        opcional porque la obligatoriedad depende del veredicto y XSD 1.0 no la expresa.
      -->
      <xs:element name="reason" type="ir:ReasonType" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <!--
    ir:ResultType: los cuatro veredictos posibles, disjuntos por diseño.
    - PASS:           el recompute coincide con el root sellado
    - FAIL:           el AIP no casa con una evidencia auténtica. Con recomputedRoot distinto de
                      sealedRoot, el recompute NO coincide (el objeto conservado ha cambiado); con
                      los dos roots IDÉNTICOS (Phase 06.2, Plan 11, D-27) el fallo es de la
                      evidencia: su firma no es íntegra o no encadena con un ancla configurada, o su
                      fixity por fichero es contradictoria. El motivo concreto lo lleva «reason».
    - NOT_ANCHORABLE: el AIP nunca fue anclado criptográficamente (no hay contra qué comparar)
    - ERROR:          la comprobación no pudo completarse (no afirma nada sobre el AIP)
    Colapsar NOT_ANCHORABLE o ERROR en FAIL produciría una alarma de integridad falsa sobre un
    AIP intacto, que es el peor defecto posible en este documento (T-05.1-04).
  -->
  <xs:simpleType name="ResultType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="PASS"/>
      <xs:enumeration value="FAIL"/>
      <xs:enumeration value="NOT_ANCHORABLE"/>
      <xs:enumeration value="ERROR"/>
    </xs:restriction>
  </xs:simpleType>

  <!--
    ir:ReasonType: motivo del veredicto, vocabulario CERRADO (decisión del usuario 0a, plan 06.7-05:
    diez valores). Un valor nuevo exige publicar un v3: los informes v2 ya sellados no se reinterpretan.
    PASS no lleva «reason».

    Motivos de ALTERACIÓN (solo aparecen con result=FAIL):
    - HASH_MISMATCH:               el hash de contenido recomputado no coincide con el sellado
    - FILES_MISSING_OR_UNEXPECTED: faltan ficheros del AIP o hay ficheros que el sidecar no declara
    - SIGNATURE_NOT_INTACT:        la firma del sidecar sellado no es íntegra
    - CHAIN_NOT_ANCHORED:          la firma del sidecar no encadena con un ancla de confianza configurada
    - NO_SIGNATURE:                el sidecar sellado no lleva firma
    - SIDECAR_UNREADABLE:          el sidecar sellado no se pudo interpretar

    Motivos de NO alteración (nunca afirman que el paquete esté alterado, T-05.1-04):
    - ANCHORS_NOT_CONFIGURED:      result=ERROR; no hay anclas de confianza configuradas para validar
    - SIGNATURE_NOT_CHECKED:       result=ERROR; el validador de firmas falló por un error técnico
    - CHECK_NOT_COMPLETED:         result=ERROR; la comprobación no pudo completarse por otra causa
    - NOT_ANCHORED:                result=NOT_ANCHORABLE; el AIP nunca fue anclado

    ERROR y NOT_ANCHORABLE jamás usan un motivo de alteración. integrity-report-v1.xsd sigue vigente
    para todo lo ya sellado y no lleva motivo.
  -->
  <xs:simpleType name="ReasonType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="HASH_MISMATCH"/>
      <xs:enumeration value="FILES_MISSING_OR_UNEXPECTED"/>
      <xs:enumeration value="SIGNATURE_NOT_INTACT"/>
      <xs:enumeration value="CHAIN_NOT_ANCHORED"/>
      <xs:enumeration value="NO_SIGNATURE"/>
      <xs:enumeration value="SIDECAR_UNREADABLE"/>
      <xs:enumeration value="ANCHORS_NOT_CONFIGURED"/>
      <xs:enumeration value="SIGNATURE_NOT_CHECKED"/>
      <xs:enumeration value="CHECK_NOT_COMPLETED"/>
      <xs:enumeration value="NOT_ANCHORED"/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
