{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://landlordatlas.com/schema/locality-record.schema.json",
  "title": "Local Rent Regulation Record",
  "description": "One record per local rent-regulation regime (D-050 Tier 1). Three shapes share this schema, split by record_type: local_ordinance = one municipality's or county's own rent regulation; state_framework = a state-law framework under which localities regulate rents (e.g. Connecticut's fair rent commissions, New York's ETPA opt-in system); no_local_regime = a locality widely but wrongly claimed to regulate rents, recorded so the absence is a stated, cited fact. Locality records attach to a state whose verified preemption posture permits local regulation; the state record's rent_regulation_preemption is the parent claim. Every substantive field must be backed by a citation in the citations array, or be null. Every current dollar/percentage figure is time-limited by nature and must ship inside current_figures with the period it applies to and the official source that published it — a bare figure with no window is a validation failure.",
  "type": "object",
  "required": [
    "state_code",
    "locality",
    "locality_slug",
    "record_type",
    "regime_name",
    "page_title",
    "topic_verified",
    "status_plain",
    "citations",
    "summary_plain"
  ],
  "properties": {
    "state_code": {
      "type": "string",
      "pattern": "^[A-Z]{2}$"
    },
    "locality": {
      "type": "string",
      "description": "Display name, e.g. 'Newark' or 'Montgomery County'"
    },
    "locality_slug": {
      "type": "string",
      "pattern": "^[a-z0-9-]+$",
      "description": "URL segment under /laws/{state}/ — must match the filename {STATE}-{slug}.json"
    },
    "record_type": {
      "enum": [
        "local_ordinance",
        "state_framework",
        "no_local_regime"
      ]
    },
    "regime_name": {
      "type": "string",
      "description": "What the regime is called, e.g. 'Rent Control', 'Rent Stabilization', 'Municipal Fair Rent Commissions'. For no_local_regime records: the claimed regime being corrected, e.g. 'Rent Stabilization (none in force)'."
    },
    "page_title": {
      "type": "string",
      "maxLength": 41,
      "description": "Short page-title label, e.g. 'Newark, NJ Rent Control'. The page appends the verified year and site name; the cap keeps the full title inside the 65-character limit."
    },
    "topic_verified": {
      "type": "string",
      "format": "date",
      "description": "Date this record was verified against official sources. Only set by an actual verification."
    },
    "status_plain": {
      "type": "string",
      "minLength": 40,
      "description": "Plain-language status: what is in force, since when, under what instrument, and the most recent amendment."
    },
    "cap_plain": {
      "type": [
        "string",
        "null"
      ],
      "description": "The rent-increase limit as plain language: formula, ceiling, frequency. null only for no_local_regime records."
    },
    "coverage_plain": {
      "type": [
        "string",
        "null"
      ],
      "description": "What housing is covered and the main exemptions."
    },
    "vacancy_plain": {
      "type": [
        "string",
        "null"
      ],
      "description": "What happens to the cap when a unit turns over."
    },
    "eviction_limits_plain": {
      "type": [
        "string",
        "null"
      ],
      "description": "Eviction or termination limits the regime itself imposes; null with a note if none."
    },
    "registration_plain": {
      "type": [
        "string",
        "null"
      ],
      "description": "Registration, licensing, or filing duties the regime imposes."
    },
    "extras_plain": {
      "type": [
        "string",
        "null"
      ],
      "description": "Other obligations the regime adds: notice periods, fee limits, surcharges, disclosure duties."
    },
    "current_figures": {
      "type": [
        "array",
        "null"
      ],
      "description": "Published figures that change on a cycle (annual allowances, guideline rates). Each figure carries the period it applies to and the official source that published it. A figure that cannot carry both does not ship.",
      "items": {
        "type": "object",
        "required": [
          "label",
          "value",
          "period",
          "source_url",
          "official"
        ],
        "additionalProperties": false,
        "properties": {
          "label": {
            "type": "string",
            "maxLength": 120
          },
          "value": {
            "type": "string",
            "description": "The figure, with any qualifier the source attaches. A derived figure states its derivation in-line."
          },
          "period": {
            "type": "string",
            "minLength": 4,
            "description": "The window the figure applies to, e.g. 'July 1, 2026 – June 30, 2027' or 'calendar year 2026'"
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "official": {
            "type": "boolean"
          }
        }
      }
    },
    "citations": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "statute",
          "url",
          "official"
        ],
        "properties": {
          "statute": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "official": {
            "type": "boolean"
          },
          "pinpoint": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "summary_plain": {
      "type": "string",
      "minLength": 100,
      "description": "Plain-language summary. The first sentence must be the quotable answer-box sentence."
    },
    "notes": {
      "oneOf": [
        {
          "type": [
            "string",
            "null"
          ]
        },
        {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": [
              "label",
              "text"
            ],
            "additionalProperties": false,
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 80
              },
              "text": {
                "type": "string"
              }
            }
          }
        }
      ],
      "description": "PUBLIC page copy (renders under Notes and caveats). Same shape as state-record topic notes."
    }
  },
  "if": {
    "properties": {
      "record_type": {
        "enum": [
          "local_ordinance",
          "state_framework"
        ]
      }
    }
  },
  "then": {
    "properties": {
      "citations": {
        "minItems": 1
      },
      "cap_plain": {
        "type": "string",
        "minLength": 40
      },
      "coverage_plain": {
        "type": "string",
        "minLength": 40
      }
    }
  },
  "else": {
    "properties": {
      "cap_plain": {
        "type": "null"
      },
      "vacancy_plain": {
        "type": "null"
      },
      "registration_plain": {
        "type": "null"
      }
    }
  }
}