{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://ballscience4u.de/machine/schema.json",
  "title": "BallScience4U Public HTML Catalog",
  "description": "Compact inventory of public HTML documents and selected source links. SHA-256 covers the exact prepared HTML bytes.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schemaVersion",
    "generatedAt",
    "site",
    "limitations",
    "entries"
  ],
  "properties": {
    "schemaVersion": {
      "const": "1.0",
      "description": "Catalog record format version."
    },
    "generatedAt": {
      "type": "string",
      "format": "date-time",
      "description": "UTC time at which this catalog was generated."
    },
    "site": {
      "type": "object",
      "description": "Identity and declared document languages for this site.",
      "additionalProperties": false,
      "required": [
        "name",
        "url",
        "languages"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "languages": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        }
      }
    },
    "limitations": {
      "type": "array",
      "description": "Interpretation limits applying to the catalog as a whole.",
      "items": {
        "type": "string"
      }
    },
    "entries": {
      "type": "array",
      "description": "One record per public or newly prepared HTML document, including this machine guide.",
      "items": {
        "$ref": "#/$defs/entry"
      }
    }
  },
  "$defs": {
    "link": {
      "type": "object",
      "description": "A relevant link found in the page source.",
      "additionalProperties": false,
      "required": [
        "rel",
        "title",
        "url"
      ],
      "properties": {
        "rel": {
          "enum": [
            "source",
            "data",
            "citation",
            "proof",
            "alternate",
            "related"
          ],
          "description": "Relation inferred from the source URL, link relation, and visible link label."
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "description": "Visible link text, title attribute, or URL path when untitled."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "Absolute URL resolved from the source link."
        }
      }
    },
    "entry": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "documentPath",
        "canonicalUrl",
        "canonicalSource",
        "title",
        "language",
        "description",
        "family",
        "indexabilityMeta",
        "noindexDeclared",
        "sourceSha256",
        "links"
      ],
      "properties": {
        "documentPath": {
          "type": "string",
          "pattern": "^/",
          "description": "Root-relative deployed document path."
        },
        "canonicalUrl": {
          "type": "string",
          "format": "uri",
          "description": "Page canonical URL, read from rel=canonical or derived from the document path."
        },
        "canonicalSource": {
          "enum": [
            "link-rel-canonical",
            "fallback-from-document-path"
          ],
          "description": "States whether canonicalUrl was explicit or derived."
        },
        "title": {
          "type": [
            "string",
            "null"
          ],
          "description": "HTML title (or og:title if title is absent); null if neither exists."
        },
        "language": {
          "type": [
            "string",
            "null"
          ],
          "description": "The document html lang value; null if not declared."
        },
        "description": {
          "type": "string",
          "description": "Meta description exactly as published; empty string if absent."
        },
        "family": {
          "type": [
            "string",
            "null"
          ],
          "description": "Release inventory family; null if the inventory did not classify the page."
        },
        "indexabilityMeta": {
          "type": "array",
          "description": "Exact robots and googlebot meta name/content pairs; HTTP headers are outside scope.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "name",
              "content"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "content": {
                "type": "string"
              }
            }
          }
        },
        "noindexDeclared": {
          "type": "boolean",
          "description": "True when an HTML robots/googlebot meta value includes noindex."
        },
        "sourceSha256": {
          "type": "string",
          "pattern": "^[a-f0-9]{64}$",
          "description": "SHA-256 of the exact prepared HTML bytes before hosting processing. Hosts such as Netlify may normalize link or form attributes; this is not a hash of the HTTP response."
        },
        "links": {
          "type": "array",
          "maxItems": 6,
          "description": "Selected relevant links parsed from this HTML source, not a complete link graph.",
          "items": {
            "$ref": "#/$defs/link"
          }
        }
      }
    }
  }
}
