{
  "$defs": {
    "AccessPolicy": {
      "additionalProperties": false,
      "description": "Access rules on a data connection, copied onto each connected dataset (POC DATA-CATALOGUE \u00a72).",
      "properties": {
        "allowed_uses": {
          "items": {
            "enum": [
              "fit",
              "score",
              "side_modelling",
              "benchmark",
              "transform"
            ],
            "type": "string"
          },
          "title": "Allowed Uses",
          "type": "array"
        },
        "copy_policy": {
          "default": "transient_only",
          "enum": [
            "allowed",
            "transient_only",
            "aggregates_only"
          ],
          "title": "Copy Policy",
          "type": "string"
        },
        "licence_limits": {
          "anyOf": [
            {
              "$ref": "#/$defs/LicenceLimits"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "min_segment_size": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "For aggregates_only; defaults to the contract's G-PRIV-01 floor.",
          "title": "Min Segment Size"
        },
        "retention_days": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "For cached copies; defaults to the client contract's retention_days (rules.effective_access).",
          "title": "Retention Days"
        }
      },
      "title": "AccessPolicy",
      "type": "object"
    },
    "Delivery": {
      "additionalProperties": false,
      "description": "G-DATA-01 intake record.",
      "properties": {
        "column_mappings": {
          "additionalProperties": {
            "type": "string"
          },
          "description": "column -> registry id",
          "title": "Column Mappings",
          "type": "object"
        },
        "contact": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Contact"
        },
        "covered_range": {
          "anyOf": [
            {
              "additionalProperties": {
                "format": "date",
                "type": "string"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Covered Range"
        },
        "file_fingerprint": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "``sha256:<hex>`` of the raw file (spec \u00a76); a bare hex digest is read and rewritten with the prefix.",
          "title": "File Fingerprint"
        },
        "known_issues": {
          "items": {
            "type": "string"
          },
          "title": "Known Issues",
          "type": "array"
        },
        "pull_date": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Pull Date"
        },
        "registered": {
          "default": true,
          "title": "Registered",
          "type": "boolean"
        },
        "source": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Source"
        }
      },
      "title": "Delivery",
      "type": "object"
    },
    "DimSpec": {
      "additionalProperties": false,
      "properties": {
        "freq": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Freq"
        },
        "kind": {
          "default": "categorical",
          "enum": [
            "categorical",
            "time",
            "integer",
            "float",
            "index"
          ],
          "title": "Kind",
          "type": "string"
        },
        "policy": {
          "default": "fixed",
          "enum": [
            "fixed",
            "extend",
            "new_levels"
          ],
          "title": "Policy",
          "type": "string"
        }
      },
      "title": "DimSpec",
      "type": "object"
    },
    "LicenceLimits": {
      "additionalProperties": false,
      "description": "Vendor or client licence limits checked before export (spec \u00a720).",
      "properties": {
        "ids": {
          "items": {
            "type": "string"
          },
          "title": "Ids",
          "type": "array"
        },
        "text": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Text"
        }
      },
      "title": "LicenceLimits",
      "type": "object"
    },
    "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"
    },
    "RecipeRef": {
      "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"
    },
    "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"
    },
    "VarSpec": {
      "additionalProperties": false,
      "properties": {
        "dims": {
          "items": {
            "type": "string"
          },
          "title": "Dims",
          "type": "array"
        },
        "dtype": {
          "default": "float64",
          "title": "Dtype",
          "type": "string"
        },
        "missing": {
          "default": "forbid",
          "enum": [
            "forbid",
            "allow",
            "mask"
          ],
          "title": "Missing",
          "type": "string"
        },
        "role": {
          "default": "covariate",
          "enum": [
            "target",
            "covariate",
            "media",
            "spend",
            "control",
            "index",
            "mask",
            "constant",
            "weight",
            "exposure"
          ],
          "title": "Role",
          "type": "string"
        },
        "units": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Units"
        }
      },
      "title": "VarSpec",
      "type": "object"
    }
  },
  "$id": "https://schemas.ump.dev/v1/dataset.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "properties": {
    "access": {
      "anyOf": [
        {
          "$ref": "#/$defs/AccessPolicy"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Copied from the connection; null on a stored dataset means the client contract's terms apply."
    },
    "annual_spend": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Annual spend per channel. Written by data (`service.py`), onboarding and experiments.",
      "title": "Annual Spend"
    },
    "approved_by": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): approver principal.",
      "title": "Governance ApprovedBy"
    },
    "audit_level": {
      "default": 2,
      "enum": [
        1,
        2,
        3,
        4
      ],
      "title": "Audit Level",
      "type": "integer"
    },
    "blob_uri": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Content-addressed blob location (POC: var/blobs).",
      "title": "Blob Uri"
    },
    "canonical_columns": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Canonical column names after mapping. Written by data (`service.py`), onboarding and experiments.",
      "title": "Canonical Columns"
    },
    "client_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Client Id"
    },
    "columns": {
      "items": {
        "type": "string"
      },
      "title": "Columns",
      "type": "array"
    },
    "connection_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "data_connection artifact id (connected only).",
      "title": "Connection Id"
    },
    "connector": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Connector kind of a connected dataset. Written by data (`service.py`), onboarding and experiments.",
      "title": "Connector"
    },
    "content_hash": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): the artifact content hash.",
      "title": "Governance ContentHash"
    },
    "delivery": {
      "$ref": "#/$defs/Delivery"
    },
    "description": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Plain description. Written by data (`service.py`), onboarding and experiments.",
      "title": "Description"
    },
    "dims": {
      "additionalProperties": {
        "$ref": "#/$defs/DimSpec"
      },
      "title": "Dims",
      "type": "object"
    },
    "extraction": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "How the data was extracted: method, tool, checks. Written by data (`service.py`), onboarding and experiments.",
      "title": "Extraction"
    },
    "extraction_rating": {
      "default": "exact",
      "enum": [
        "exact",
        "parsed",
        "read",
        "retyped"
      ],
      "title": "Extraction Rating",
      "type": "string"
    },
    "fingerprint_basis": {
      "anyOf": [
        {
          "enum": [
            "file_bytes",
            "canonical_rows"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Filled from storage when absent: file_bytes (stored) or canonical_rows (connected).",
      "title": "Fingerprint Basis"
    },
    "fit_hints": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Hints for a first fit: date and KPI columns, channels, controls. Written by data (`service.py`), onboarding and experiments.",
      "title": "Fit Hints"
    },
    "gate_results": {
      "anyOf": [
        {
          "items": {},
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): gate results of the latest run.",
      "title": "Governance GateResults"
    },
    "id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): artifact id.",
      "title": "Governance Id"
    },
    "layout": {
      "default": "long",
      "enum": [
        "dense",
        "long"
      ],
      "title": "Layout",
      "type": "string"
    },
    "mapping": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Column mapping onto canonical names. Written by data (`service.py`), onboarding and experiments.",
      "title": "Mapping"
    },
    "mapping_stale": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Why the stored mapping no longer fits the source. Written by data (`service.py`), onboarding and experiments.",
      "title": "Mapping Stale"
    },
    "materialization": {
      "default": "none",
      "description": "cached: a copy is kept in the blob store, only when access.copy_policy is allowed.",
      "enum": [
        "none",
        "cached"
      ],
      "title": "Materialization",
      "type": "string"
    },
    "n_rows": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "N Rows"
    },
    "name": {
      "title": "Name",
      "type": "string"
    },
    "notes": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Note codes. Written by data (`service.py`), onboarding and experiments.",
      "title": "Notes"
    },
    "owner": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): owner principal.",
      "title": "Governance Owner"
    },
    "previous_fingerprint": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Fingerprint before the latest refresh. Written by data (`service.py`), onboarding and experiments.",
      "title": "Previous Fingerprint"
    },
    "recipe": {
      "anyOf": [
        {
          "$ref": "#/$defs/RecipeRef"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "How this dataset was made: a pointer to the transform recipe uploaded with it (G-DATA-06). Null for raw deliveries and datasets uploaded without one."
    },
    "recipe_check": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "G-DATA-06 recipe check result. Written by data (`service.py`), onboarding and experiments.",
      "title": "Recipe Check"
    },
    "ref": {
      "description": "dataset://{scope}/{name}@sha256:{hash}",
      "title": "Ref",
      "type": "string"
    },
    "refreshed_at": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Last refresh, RFC 3339. Written by data (`service.py`), onboarding and experiments.",
      "title": "Refreshed At"
    },
    "request_spec": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Query or request spec for the connector (connected only). Never holds secrets.",
      "title": "Request Spec"
    },
    "revision": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): content revision (spec \u00a77).",
      "title": "Governance Revision"
    },
    "role": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Role of the dataset, e.g. raw_delivery or derived. Written by data (`service.py`), onboarding and experiments.",
      "title": "Role"
    },
    "scope": {
      "title": "Scope",
      "type": "string"
    },
    "sha256": {
      "title": "Sha256",
      "type": "string"
    },
    "source_format": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Source file format, e.g. csv. Written by data (`service.py`), onboarding and experiments.",
      "title": "Source Format"
    },
    "state": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): lifecycle state of the version.",
      "title": "Governance State"
    },
    "storage": {
      "default": "stored",
      "description": "stored: a file in the blob store; connected: read through a data_connection when used, rows not kept.",
      "enum": [
        "stored",
        "connected"
      ],
      "title": "Storage",
      "type": "string"
    },
    "submitted_by": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Governance member (spec \u00a76): submitter principal.",
      "title": "Governance SubmittedBy"
    },
    "tie_out": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Tie-out against printed totals (tolerance proposed). Written by data (`service.py`), onboarding and experiments.",
      "title": "Tie Out"
    },
    "tool_error_rate": {
      "anyOf": [
        {
          "maximum": 1,
          "minimum": 0,
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Tool Error Rate"
    },
    "totals_check": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "G-DATA-02 extracted vs printed.",
      "title": "Totals Check"
    },
    "truth": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Known truth of a synthetic panel (synthetic data only). Written by data (`service.py`), onboarding and experiments.",
      "title": "Truth"
    },
    "valid_to": {
      "default": null,
      "description": "Governance member (spec \u00a76): end of the validity window (spec \u00a77).",
      "title": "Governance ValidTo"
    },
    "vars": {
      "additionalProperties": {
        "$ref": "#/$defs/VarSpec"
      },
      "title": "Vars",
      "type": "object"
    }
  },
  "required": [
    "ref",
    "scope",
    "name",
    "sha256"
  ],
  "title": "Dataset",
  "type": "object"
}
