{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.waterparliament.net/assets/nvdm/envelope.schema.json",
  "title": "NVDM v1 envelope (registry data contract)",
  "description": "Draft derived from the Neer Vazhvu Data Model v1.0, Part 5. The normative schema is maintained with the specification by Neer Vazhvu. Envelope keys are never underscore-prefixed; payload keys sit beside them and are governed by each dataset's own contract.",
  "type": "object",
  "required": ["nvdm", "dataset", "scope", "provenance"],
  "properties": {
    "nvdm": { "type": "string", "pattern": "^1\\.[0-9]+(\\.[0-9]+)?$", "description": "Specification version this artifact claims." },
    "dataset": {
      "type": "string",
      "pattern": "^(data-root|geojson-layers|cascade|basins|rich-bodies|corridors|ingres)/[a-z0-9]+(-[a-z0-9]+)*$",
      "description": "Logical dataset id, <family>/<stem>. Must agree with the artifact's path."
    },
    "scope": { "$ref": "#/$defs/scope" },
    "provenance": {
      "type": "object",
      "required": ["sources", "method", "produced_at", "produced_by"],
      "properties": {
        "sources": { "type": "array", "items": { "$ref": "#/$defs/source" } },
        "method": { "type": "string", "enum": ["manual", "scrape", "api", "pdf-extract", "gee", "derived", "mixed"] },
        "produced_at": { "$ref": "#/$defs/date" },
        "produced_by": { "type": "string", "minLength": 1, "description": "Script path, or \"manual\"." },
        "note": { "oneOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] },
        "conventions": { "type": "object", "additionalProperties": { "type": "string" } }
      }
    },
    "projection": {
      "type": "object",
      "required": ["of", "method"],
      "properties": {
        "of": { "$ref": "#/$defs/scope" },
        "method": {
          "type": "string",
          "enum": ["direct-published", "identifier-crosswalk", "spatial-intersection", "area-weighted", "station-assignment", "interpolation", "service-relation", "administrative-rollup", "administrative-proxy", "expert-mapped"]
        },
        "limitations": { "type": "array", "items": { "type": "string" } }
      }
    },
    "ext": { "type": "object", "description": "Per-scope extensions, namespaced by concern. Must not shadow core keys." }
  },
  "$defs": {
    "date": { "type": "string", "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01]))?$", "description": "ISO 8601 date or year-month; calendar validity is checked by the validator." },
    "scope": {
      "type": "object",
      "required": ["kind", "id"],
      "properties": {
        "kind": { "type": "string", "enum": ["city", "region", "basin", "corridor", "district", "state"] },
        "id": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" }
      }
    },
    "source": {
      "type": "object",
      "required": ["title", "publisher"],
      "properties": {
        "id": { "type": "string", "description": "Source registry id. Required when the source is registered; per-record references join on it." },
        "title": { "type": "string", "minLength": 1 },
        "publisher": { "type": "string", "minLength": 1 },
        "url": { "type": "string", "format": "uri" },
        "license": { "type": "string", "description": "Required for any source whose values are redistributed." },
        "as_of": { "$ref": "#/$defs/date" },
        "retrieved": { "$ref": "#/$defs/date" },
        "closed": { "type": "boolean", "description": "One-time document; requires as_of." },
        "role": { "type": "string", "enum": ["asserts", "input", "methodology"] }
      },
      "if": { "properties": { "closed": { "const": true } }, "required": ["closed"] },
      "then": { "required": ["as_of"] }
    }
  }
}
