{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:cede:schema:model-primitives:v0",
  "title": "CEDE model builder primitives, v0",
  "description": "Everything a v1 model can be composed from, enumerated: the pinned feeds and the measurements each publishes, the transforms, and the payout functions. SPEC.md section 2A fixes the vocabulary at exactly four primitives — a feed, a measurement, a transform and a payout function — and this document is how a caller discovers what is in each of the four today. It names feeds and what they measure; it never serves feed content, so nothing in it can carry an individual-level record (SPEC.md section 4, P10).",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "vocabulary", "feeds", "transforms", "payout_functions"],
  "properties": {
    "schema_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
    "vocabulary": {
      "type": "object",
      "additionalProperties": false,
      "required": ["note", "primitives"],
      "properties": {
        "note": { "type": "string", "minLength": 1 },
        "primitives": {
          "type": "array",
          "items": { "enum": ["feed", "measurement", "transform", "payout"] },
          "minItems": 4,
          "maxItems": 4,
          "uniqueItems": true,
          "description": "Exactly four, pinned by minItems and maxItems: a fifth primitive is a change to the v1 vocabulary and needs a SPEC.md section 8 amendment, not a schema edit."
        }
      }
    },
    "feeds": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "version",
          "name",
          "publisher",
          "kind",
          "licence",
          "aggregation_level",
          "period_of_record",
          "measurements"
        ],
        "properties": {
          "id": { "type": "string", "minLength": 1 },
          "version": { "type": "string", "minLength": 1 },
          "name": { "type": "string" },
          "publisher": { "type": "string" },
          "kind": { "type": "string" },
          "licence": { "type": "object" },
          "aggregation_level": {
            "type": "object",
            "description": "The feed's declared aggregation level (SPEC.md section 4, P10). Published here so a model author can see what the feed is before composing on it."
          },
          "period_of_record": { "type": "object" },
          "measurements": {
            "type": "array",
            "description": "The variables this build can read from the feed. An empty list means the platform holds the snapshot but has no reader for its kind yet, so the builder will refuse it by name rather than guess at its columns.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["variable", "unit"],
              "properties": {
                "variable": { "type": "string", "minLength": 1 },
                "unit": { "type": "string", "minLength": 1 }
              }
            }
          }
        }
      }
    },
    "transforms": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["type", "description", "parameters", "index_unit"],
        "properties": {
          "type": { "type": "string", "minLength": 1 },
          "description": { "type": "string", "minLength": 1 },
          "parameters": { "type": "object" },
          "index_unit": { "type": "string", "minLength": 1 }
        }
      }
    },
    "payout_functions": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["type", "description", "parameters"],
        "properties": {
          "type": { "type": "string", "minLength": 1 },
          "description": { "type": "string", "minLength": 1 },
          "parameters": { "type": "object" }
        }
      }
    }
  }
}
