{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://dormsorted.com/datasets/dorm-rules-index/dorm-rules-index.schema.json",
  "title": "Dorm, Sorted. Dorm Rules Index",
  "description": "Public contract for a versioned Dorm Rules Index release. Published records retain official sources, exact scope, conditions, exceptions, and a current verification event.",
  "type": "object",
  "required": [
    "$schema",
    "schemaVersion",
    "dataset",
    "methodology",
    "records",
    "analyses",
    "dataDictionary",
    "versionHistory",
    "citation",
    "corrections"
  ],
  "properties": {
    "$schema": { "type": "string", "format": "uri" },
    "schemaVersion": { "const": 1 },
    "dataset": {
      "type": "object",
      "required": ["id", "name", "description", "version", "publishedDate", "cutoffDate", "publisher", "reportPath", "reportUrl", "methodologyPath", "methodologyUrl", "schemaPath", "schemaUrl", "coverage", "distributions"],
      "properties": {
        "id": { "const": "dorm-sorted-dorm-rules-index" },
        "name": { "type": "string", "minLength": 1 },
        "description": { "type": "string", "minLength": 1 },
        "version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
        "publishedDate": { "$ref": "#/$defs/date" },
        "cutoffDate": { "$ref": "#/$defs/date" },
        "publisher": { "const": "Dorm, Sorted." },
        "reportPath": { "type": "string", "pattern": "^/.*?/$" },
        "reportUrl": { "type": "string", "format": "uri" },
        "methodologyPath": { "type": "string", "pattern": "^/.*?/$" },
        "methodologyUrl": { "type": "string", "format": "uri" },
        "schemaPath": { "type": "string", "pattern": "^/.*?\\.json$" },
        "schemaUrl": { "type": "string", "format": "uri" },
        "coverage": {
          "type": "object",
          "required": ["recordCount", "institutionCount", "institutions", "geography", "representativeness"],
          "properties": {
            "recordCount": { "type": "integer", "minimum": 1 },
            "institutionCount": { "type": "integer", "minimum": 1 },
            "institutions": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
            "geography": { "type": "string", "minLength": 1 },
            "representativeness": { "type": "string", "minLength": 1 }
          },
          "additionalProperties": false
        },
        "distributions": {
          "type": "array",
          "minItems": 2,
          "items": {
            "type": "object",
            "required": ["label", "encodingFormat", "path", "url"],
            "properties": {
              "label": { "type": "string", "minLength": 1 },
              "encodingFormat": { "enum": ["application/json", "text/csv"] },
              "path": { "type": "string", "pattern": "^/datasets/" },
              "url": { "type": "string", "format": "uri" }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    },
    "methodology": {
      "type": "object",
      "required": ["inclusionCriteria", "scope", "dataCutoff", "verificationProcess", "missingDataTreatment", "conflictResolution", "knownLimitations", "topicClassification", "reproducibility", "sourceMethodologyUrl"],
      "properties": {
        "inclusionCriteria": { "$ref": "#/$defs/nonEmptyStrings" },
        "scope": { "type": "string", "minLength": 1 },
        "dataCutoff": { "type": "string", "minLength": 1 },
        "verificationProcess": { "type": "string", "minLength": 1 },
        "missingDataTreatment": { "type": "string", "minLength": 1 },
        "conflictResolution": { "type": "string", "minLength": 1 },
        "knownLimitations": { "$ref": "#/$defs/nonEmptyStrings" },
        "topicClassification": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": ["topic", "rule"],
            "properties": {
              "topic": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
              "rule": { "type": "string", "minLength": 1 }
            },
            "additionalProperties": false
          }
        },
        "reproducibility": { "type": "string", "minLength": 1 },
        "sourceMethodologyUrl": { "type": "string", "format": "uri" }
      },
      "additionalProperties": false
    },
    "records": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/record" }
    },
    "analyses": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/analysis" }
    },
    "dataDictionary": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["field", "label", "type", "description"],
        "properties": {
          "field": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
          "label": { "type": "string", "minLength": 1 },
          "type": { "type": "string", "minLength": 1 },
          "description": { "type": "string", "minLength": 1 }
        },
        "additionalProperties": false
      }
    },
    "versionHistory": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["version", "publishedDate", "cutoffDate", "recordCount", "summary", "jsonPath", "csvPath"],
        "properties": {
          "version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
          "publishedDate": { "$ref": "#/$defs/date" },
          "cutoffDate": { "$ref": "#/$defs/date" },
          "recordCount": { "type": "integer", "minimum": 1 },
          "summary": { "type": "string", "minLength": 1 },
          "jsonPath": { "type": "string", "pattern": "^/datasets/.*\\.json$" },
          "csvPath": { "type": "string", "pattern": "^/datasets/.*\\.csv$" }
        },
        "additionalProperties": false
      }
    },
    "citation": {
      "type": "object",
      "required": ["recommended", "individualRecord", "accessDate", "stableUrl"],
      "properties": {
        "recommended": { "type": "string", "minLength": 1 },
        "individualRecord": { "type": "string", "minLength": 1 },
        "accessDate": { "type": "string", "minLength": 1 },
        "stableUrl": { "type": "string", "format": "uri" }
      },
      "additionalProperties": false
    },
    "corrections": {
      "type": "object",
      "required": ["url", "instructions", "privacy"],
      "properties": {
        "url": { "type": "string", "format": "uri" },
        "instructions": { "type": "string", "minLength": 1 },
        "privacy": { "type": "string", "minLength": 1 }
      },
      "additionalProperties": false
    }
  },
  "$defs": {
    "date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
    "nullableId": { "type": ["string", "null"] },
    "nonEmptyStrings": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } },
    "scope": {
      "type": "object",
      "required": ["systemId", "institutionId", "campusId", "residenceHallId", "roomTypeId", "academicYear", "label"],
      "properties": {
        "systemId": { "$ref": "#/$defs/nullableId" },
        "institutionId": { "type": "string", "minLength": 1 },
        "campusId": { "$ref": "#/$defs/nullableId" },
        "residenceHallId": { "$ref": "#/$defs/nullableId" },
        "roomTypeId": { "$ref": "#/$defs/nullableId" },
        "academicYear": { "$ref": "#/$defs/nullableId" },
        "label": { "type": "string", "minLength": 1 }
      },
      "additionalProperties": false
    },
    "source": {
      "type": "object",
      "required": ["id", "title", "publisher", "url", "sourceType", "dateAccessed", "lastVerifiedDate", "lastAutomatedCheckAt", "nextAutomatedCheckAt", "automatedReviewState", "verificationMethod", "archiveState", "publicationState"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "title": { "type": "string", "minLength": 1 },
        "publisher": { "type": "string", "minLength": 1 },
        "url": { "type": "string", "format": "uri", "pattern": "^https://" },
        "sourceType": { "type": "string", "minLength": 1 },
        "dateAccessed": { "$ref": "#/$defs/date" },
        "lastVerifiedDate": { "$ref": "#/$defs/date" },
        "lastAutomatedCheckAt": { "type": "string", "format": "date-time" },
        "nextAutomatedCheckAt": { "type": "string", "format": "date-time" },
        "automatedReviewState": { "const": "approved" },
        "verificationMethod": { "type": "string", "minLength": 1 },
        "archiveState": { "const": "current" },
        "publicationState": { "const": "published" }
      },
      "additionalProperties": false
    },
    "verification": {
      "type": "object",
      "required": ["eventId", "method", "authority", "authorityId", "decision", "approved", "consensusResult", "confidence", "lastVerifiedDate", "reviewedAt", "verificationExpiresAt", "policyVersion", "pipelineVersion", "publicationState"],
      "properties": {
        "eventId": { "type": "string", "minLength": 1 },
        "method": { "type": "string", "minLength": 1 },
        "authority": { "type": "string", "minLength": 1 },
        "authorityId": { "type": "string", "minLength": 1 },
        "decision": { "const": "approved" },
        "approved": { "const": true },
        "consensusResult": { "type": "string", "minLength": 1 },
        "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
        "lastVerifiedDate": { "$ref": "#/$defs/date" },
        "reviewedAt": { "type": "string", "format": "date-time" },
        "verificationExpiresAt": { "$ref": "#/$defs/date" },
        "policyVersion": { "type": "string", "minLength": 1 },
        "pipelineVersion": { "type": "string", "minLength": 1 },
        "publicationState": { "const": "published" }
      },
      "additionalProperties": false
    },
    "record": {
      "type": "object",
      "required": ["id", "institution", "subject", "topics", "status", "definitive", "statement", "scope", "conditions", "exceptions", "effectiveAcademicYear", "officialSources", "verification", "publicationState"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "institution": {
          "type": "object",
          "required": ["id", "name"],
          "properties": {
            "id": { "type": "string", "minLength": 1 },
            "name": { "type": "string", "minLength": 1 }
          },
          "additionalProperties": false
        },
        "subject": {
          "type": "object",
          "required": ["type", "id", "name"],
          "properties": {
            "type": { "enum": ["item", "amenity"] },
            "id": { "type": "string", "minLength": 1 },
            "name": { "type": "string", "minLength": 1 }
          },
          "additionalProperties": false
        },
        "topics": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" } },
        "status": { "enum": ["provided", "allowed", "prohibited", "restricted", "verify", "unknown"] },
        "definitive": { "type": "boolean" },
        "statement": { "type": "string", "minLength": 1 },
        "scope": { "$ref": "#/$defs/scope" },
        "conditions": { "type": "array", "items": { "type": "string" } },
        "exceptions": { "type": "array", "items": { "type": "string" } },
        "effectiveAcademicYear": { "type": ["string", "null"] },
        "officialSources": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/source" } },
        "verification": { "$ref": "#/$defs/verification" },
        "publicationState": { "const": "published" }
      },
      "additionalProperties": false
    },
    "analysis": {
      "type": "object",
      "required": ["id", "title", "summary", "numerator", "denominator", "population", "cutoffDate", "missingDataTreatment", "datasetVersion", "methodologyUrl", "breakdownLabel", "breakdown"],
      "properties": {
        "id": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
        "title": { "type": "string", "minLength": 1 },
        "summary": { "type": "string", "minLength": 1 },
        "numerator": { "type": "integer", "minimum": 0 },
        "denominator": { "type": "integer", "minimum": 1 },
        "population": { "type": "string", "minLength": 1 },
        "cutoffDate": { "$ref": "#/$defs/date" },
        "missingDataTreatment": { "type": "string", "minLength": 1 },
        "datasetVersion": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
        "methodologyUrl": { "type": "string", "format": "uri" },
        "breakdownLabel": { "type": "string", "minLength": 1 },
        "breakdown": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": ["label", "count"],
            "properties": {
              "label": { "type": "string", "minLength": 1 },
              "count": { "type": "integer", "minimum": 0 }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
