{
  "$defs": {
    "RecipeExternalInput": {
      "additionalProperties": false,
      "description": "A recipe input with no catalogued match in the client's scope (``UNCATALOGUED_INPUT``).",
      "properties": {
        "catalogue_fingerprint": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Catalogue Fingerprint"
        },
        "fingerprint_seen": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "fetch_record.fingerprint_seen the recipe carried, kept so the hash a catalogue read saw is not lost.",
          "title": "Fingerprint Seen"
        },
        "input_id": {
          "title": "Input Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "sha256": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Sha256"
        },
        "source": {
          "default": "file",
          "enum": [
            "file",
            "catalogue",
            "in_memory"
          ],
          "title": "Source",
          "type": "string"
        }
      },
      "required": [
        "input_id"
      ],
      "title": "RecipeExternalInput",
      "type": "object"
    },
    "RecipeInputMatch": {
      "additionalProperties": false,
      "description": "A recipe input matched to a catalogued dataset in the same client's scope (a ``derived_from`` edge).",
      "properties": {
        "dataset_id": {
          "title": "Dataset Id",
          "type": "string"
        },
        "dataset_version": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The version of the matched dataset whose hash the input matched (its derived_from edge points at that dataset).",
          "title": "Dataset Version"
        },
        "input_id": {
          "title": "Input Id",
          "type": "string"
        },
        "matched_by": {
          "description": "sha256: file or blob bytes; catalogue_fingerprint: canonical rows of a connected dataset; dataset_id: read from the catalogue and its hashes agree; dataset_id_drifted: the input names this dataset but no catalogued version's hash agrees (the source changed since it was catalogued, note DATA_DRIFTED). The dataset's access terms apply either way.",
          "enum": [
            "sha256",
            "catalogue_fingerprint",
            "dataset_id",
            "dataset_id_drifted"
          ],
          "title": "Matched By",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        }
      },
      "required": [
        "input_id",
        "dataset_id",
        "matched_by"
      ],
      "title": "RecipeInputMatch",
      "type": "object"
    },
    "RecipeVerificationRef": {
      "additionalProperties": false,
      "description": "The recipe's own verification as uploaded. Self-reported: ``apps/data`` never replays a recipe.",
      "properties": {
        "checked_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Checked At"
        },
        "checked_by": {
          "anyOf": [
            {
              "const": "self",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Always 'self' when checked: the analyst's machine ran the replay, not UMP.",
          "title": "Checked By"
        },
        "first_divergent_step": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Step id (or 'output') where a replay first differed; only with not_reproduced.",
          "title": "First Divergent Step"
        },
        "status": {
          "default": "not_checked",
          "enum": [
            "not_checked",
            "reproduced",
            "not_reproduced",
            "not_replayable",
            "inputs_missing"
          ],
          "title": "Status",
          "type": "string"
        }
      },
      "title": "RecipeVerificationRef",
      "type": "object"
    }
  },
  "$id": "https://schemas.ump.dev/v1/recipe-ref.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "What a catalogued dataset keeps of its recipe (``Dataset.recipe``). The body lives in the blob store.",
  "properties": {
    "blob_uri": {
      "description": "blob://sha256/<hex> of the recipe JSON as uploaded.",
      "title": "Blob Uri",
      "type": "string"
    },
    "capture": {
      "default": "full",
      "enum": [
        "full",
        "partial"
      ],
      "title": "Capture",
      "type": "string"
    },
    "inputs_external": {
      "items": {
        "$ref": "#/$defs/RecipeExternalInput"
      },
      "title": "Inputs External",
      "type": "array"
    },
    "inputs_matched": {
      "items": {
        "$ref": "#/$defs/RecipeInputMatch"
      },
      "title": "Inputs Matched",
      "type": "array"
    },
    "output_matches": {
      "description": "output.sha256 equals the uploaded file's sha256. False: the recipe describes a different file (RECIPE_OUTPUT_MISMATCH).",
      "title": "Output Matches",
      "type": "boolean"
    },
    "recipe_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Recipe Id"
    },
    "sha256": {
      "description": "sha256 hex of the recipe JSON bytes; the only part of a recipe a Merkle leaf may hold.",
      "title": "Sha256",
      "type": "string"
    },
    "steps": {
      "description": "Number of recorded steps.",
      "minimum": 0,
      "title": "Steps",
      "type": "integer"
    },
    "title": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Title"
    },
    "verification": {
      "$ref": "#/$defs/RecipeVerificationRef"
    }
  },
  "required": [
    "blob_uri",
    "sha256",
    "steps",
    "output_matches"
  ],
  "title": "RecipeRef",
  "type": "object"
}
