{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://pruefberichte.shopitech.de/summary.schema.json",
  "title": "Prüfergebnis einer Shopitech-Demo (reports/summary.json)",
  "description": "Verbindlich für alle Demos. Erzeugt von ci/local/pruefen.sh bzw. den CI-Vorlagen. Ein Abschnitt ist null, wenn die Prüfung nicht ausgeführt wurde; dann steht der Grund in 'nichtGeprueft'.",
  "type": "object",
  "required": ["demo", "url", "commit", "datum", "trivy", "sbom", "axe", "lighthouse", "e2e", "lizenzen"],
  "additionalProperties": false,
  "properties": {
    "$schema": { "type": "string" },
    "demo": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$", "description": "Kurzname, z. B. musterstadt" },
    "titel": { "type": "string", "minLength": 1, "description": "Anzeigename, z. B. Musterstadt (TYPO3)" },
    "url": { "type": "string", "format": "uri", "pattern": "^https?://" },
    "commit": { "type": "string", "pattern": "^[0-9a-f]{7,40}$" },
    "datum": { "type": "string", "format": "date-time" },
    "gepruefteUrl": { "type": "string", "format": "uri", "description": "Adresse, gegen die E2E, axe und Lighthouse liefen (lokal oder live)" },
    "trivy": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "object",
          "required": ["kritisch", "hoch", "mitFix", "images"],
          "additionalProperties": false,
          "properties": {
            "kritisch": { "$ref": "#/$defs/anzahl", "description": "kritische Lücken in allen Images" },
            "hoch": { "$ref": "#/$defs/anzahl", "description": "hohe Lücken in allen Images" },
            "mitFix": { "$ref": "#/$defs/anzahl", "description": "kritische Lücken, für die ein Fix verfügbar ist (Abbruchkriterium)" },
            "hochMitFix": { "$ref": "#/$defs/anzahl" },
            "images": { "type": "array", "items": { "type": "string", "minLength": 1 } },
            "dateisystem": {
              "type": "object",
              "required": ["kritisch", "hoch", "mitFix"],
              "additionalProperties": false,
              "properties": {
                "kritisch": { "$ref": "#/$defs/anzahl" },
                "hoch": { "$ref": "#/$defs/anzahl" },
                "mitFix": { "$ref": "#/$defs/anzahl" }
              }
            },
            "version": { "type": "string" }
          }
        }
      ]
    },
    "sbom": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["image", "datei", "komponenten"],
            "additionalProperties": false,
            "properties": {
              "image": { "type": "string", "minLength": 1 },
              "datei": { "type": "string", "pattern": "^[A-Za-z0-9._-]+\\.cdx\\.json$" },
              "komponenten": { "$ref": "#/$defs/anzahl" },
              "format": { "type": "string" }
            }
          }
        }
      ]
    },
    "axe": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "object",
          "required": ["seiten", "serious", "critical"],
          "additionalProperties": false,
          "properties": {
            "seiten": { "$ref": "#/$defs/anzahl", "description": "geprüfte Seitenansichten (Seite × Gerät × Zustand)" },
            "serious": { "$ref": "#/$defs/anzahl" },
            "critical": { "$ref": "#/$defs/anzahl" },
            "moderate": { "$ref": "#/$defs/anzahl" },
            "minor": { "$ref": "#/$defs/anzahl" },
            "regeln": { "type": "string", "description": "z. B. WCAG 2.2 A/AA" },
            "version": { "type": "string" }
          }
        }
      ]
    },
    "lighthouse": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["seite", "geraet", "performance", "accessibility", "bestPractices", "seo"],
            "additionalProperties": false,
            "properties": {
              "seite": { "type": "string", "pattern": "^/" },
              "geraet": { "enum": ["mobil", "desktop"] },
              "performance": { "$ref": "#/$defs/punkte" },
              "accessibility": { "$ref": "#/$defs/punkte" },
              "bestPractices": { "$ref": "#/$defs/punkte" },
              "seo": { "$ref": "#/$defs/punkte" },
              "seoOhneCrawlable": { "type": "boolean", "description": "true: Audit is-crawlable übersprungen, weil die Demo absichtlich noindex ausliefert" },
              "lcpMs": { "type": "number", "minimum": 0 },
              "cls": { "type": "number", "minimum": 0 }
            }
          }
        }
      ]
    },
    "e2e": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "object",
          "required": ["bestanden", "fehlgeschlagen"],
          "additionalProperties": false,
          "properties": {
            "bestanden": { "$ref": "#/$defs/anzahl" },
            "fehlgeschlagen": { "$ref": "#/$defs/anzahl" },
            "uebersprungen": { "$ref": "#/$defs/anzahl" },
            "instabil": { "$ref": "#/$defs/anzahl", "description": "erst im Wiederholungslauf bestanden" }
          }
        }
      ]
    },
    "lizenzen": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "object",
          "required": ["geprueft", "abweichungen"],
          "additionalProperties": false,
          "properties": {
            "geprueft": { "$ref": "#/$defs/anzahl" },
            "abweichungen": { "$ref": "#/$defs/anzahl" },
            "ausnahmen": { "$ref": "#/$defs/anzahl", "description": "begründete Ausnahmen aus pruefung.json" },
            "oekosysteme": { "type": "array", "items": { "enum": ["npm", "composer", "maven"] } }
          }
        }
      ]
    },
    "nichtGeprueft": {
      "type": "object",
      "description": "Schritt → Grund, z. B. { \"lizenzen\": \"keine Abhängigkeiten\" }",
      "additionalProperties": { "type": "string" }
    },
    "bestanden": { "type": "boolean", "description": "alle Grenzwerte aus CONVENTIONS.md Abschnitt 4 eingehalten" },
    "verstoesse": { "type": "array", "items": { "type": "string" } },
    "pruefkette": { "type": "string", "description": "Version der Prüfkette (01-foundation-quality-and-starter)" }
  },
  "$defs": {
    "anzahl": { "type": "integer", "minimum": 0 },
    "punkte": { "type": "integer", "minimum": 0, "maximum": 100 }
  }
}
