{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://tikki.wiki/schemas/merchant-product-feed.schema.json",
  "title": "TIKKI Merchant Product Feed",
  "description": "Validated merchant input. Publication state and public JSON-LD are generated by TIKKI after review and are never accepted from the upload.",
  "type": "object",
  "required": [
    "schema_version",
    "merchant",
    "products"
  ],
  "properties": {
    "schema_version": {
      "const": "tikki.merchant-product-feed.v1"
    },
    "merchant": {
      "$ref": "#/$defs/merchant"
    },
    "products": {
      "type": "array",
      "minItems": 1,
      "maxItems": 1000,
      "items": {
        "$ref": "#/$defs/product"
      }
    }
  },
  "additionalProperties": false,
  "$defs": {
    "merchant": {
      "type": "object",
      "required": [
        "merchant_id",
        "name",
        "verified_domain"
      ],
      "properties": {
        "merchant_id": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9_-]{2,63}$"
        },
        "name": {
          "type": "string",
          "minLength": 2,
          "maxLength": 200
        },
        "verified_domain": {
          "type": "string",
          "format": "hostname"
        }
      },
      "additionalProperties": false
    },
    "identifier": {
      "type": "object",
      "required": [
        "type",
        "value"
      ],
      "properties": {
        "type": {
          "enum": [
            "gtin",
            "mpn",
            "sku"
          ]
        },
        "value": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        }
      },
      "additionalProperties": false
    },
    "image": {
      "type": "object",
      "required": [
        "url",
        "alt",
        "rights_confirmed"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://"
        },
        "alt": {
          "type": "string",
          "minLength": 2,
          "maxLength": 300
        },
        "rights_confirmed": {
          "const": true
        }
      },
      "additionalProperties": false
    },
    "attribute": {
      "type": "object",
      "required": [
        "name",
        "value"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120
        },
        "value": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500
        }
      },
      "additionalProperties": false
    },
    "claim": {
      "type": "object",
      "required": [
        "text",
        "claim_type",
        "evidence_status",
        "source_url"
      ],
      "properties": {
        "text": {
          "type": "string",
          "minLength": 2,
          "maxLength": 1000
        },
        "claim_type": {
          "enum": [
            "factual",
            "performance",
            "environmental",
            "health",
            "safety"
          ]
        },
        "evidence_status": {
          "enum": [
            "merchant_declared",
            "source_attached"
          ]
        },
        "source_url": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://"
        }
      },
      "additionalProperties": false
    },
    "offer": {
      "type": "object",
      "required": [
        "url",
        "price",
        "price_currency",
        "availability",
        "observed_at"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://"
        },
        "price": {
          "type": "number",
          "minimum": 0
        },
        "price_currency": {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        "availability": {
          "enum": [
            "in_stock",
            "out_of_stock",
            "preorder",
            "backorder",
            "discontinued"
          ]
        },
        "observed_at": {
          "type": "string",
          "format": "date-time"
        }
      },
      "additionalProperties": false
    },
    "provenance": {
      "type": "object",
      "required": [
        "source_url",
        "rights_confirmed",
        "updated_at"
      ],
      "properties": {
        "source_url": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://"
        },
        "rights_confirmed": {
          "const": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        },
        "ai_generated_fields": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string",
            "maxLength": 100
          }
        }
      },
      "additionalProperties": false
    },
    "product": {
      "type": "object",
      "required": [
        "product_id",
        "name",
        "description",
        "language",
        "brand",
        "canonical_url",
        "identifiers",
        "images",
        "attributes",
        "offers",
        "provenance"
      ],
      "properties": {
        "product_id": {
          "type": "string",
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{1,99}$"
        },
        "variant_of": {
          "type": "string",
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{1,99}$"
        },
        "name": {
          "type": "string",
          "minLength": 2,
          "maxLength": 300
        },
        "description": {
          "type": "string",
          "minLength": 20,
          "maxLength": 10000
        },
        "language": {
          "type": "string",
          "pattern": "^[a-z]{2,3}(?:-[A-Z]{2})?$"
        },
        "brand": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "category": {
          "type": "string",
          "maxLength": 300
        },
        "canonical_url": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://"
        },
        "identifiers": {
          "type": "array",
          "minItems": 1,
          "maxItems": 10,
          "items": {
            "$ref": "#/$defs/identifier"
          }
        },
        "images": {
          "type": "array",
          "minItems": 1,
          "maxItems": 20,
          "items": {
            "$ref": "#/$defs/image"
          }
        },
        "attributes": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/attribute"
          }
        },
        "claims": {
          "type": "array",
          "maxItems": 50,
          "items": {
            "$ref": "#/$defs/claim"
          }
        },
        "offers": {
          "type": "array",
          "maxItems": 50,
          "items": {
            "$ref": "#/$defs/offer"
          }
        },
        "provenance": {
          "$ref": "#/$defs/provenance"
        }
      },
      "additionalProperties": false
    }
  }
}
