{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://landlordatlas.com/schema/state-record.schema.json",
  "title": "State Landlord-Tenant Law Record",
  "description": "One record per US state covering the four v1 topics plus eviction_process (v2 — required since 2026-07-26, when all 50 verified records landed and the pages shipped). Every substantive field must be backed by a citation in its topic's citations array, or be null with an explanatory note.",
  "type": "object",
  "required": [
    "state",
    "state_code",
    "last_verified",
    "verified_by_method",
    "security_deposits",
    "rent_increase_notice",
    "late_fees",
    "entry_notice",
    "eviction_process"
  ],
  "properties": {
    "state": {
      "type": "string",
      "description": "Full state name, e.g. 'Michigan'"
    },
    "state_code": {
      "type": "string",
      "pattern": "^[A-Z]{2}$"
    },
    "last_verified": {
      "type": "string",
      "format": "date",
      "description": "Date of last verification pass against official sources. Only set by an actual verification, never by editing."
    },
    "verified_by_method": {
      "type": "string",
      "description": "How verification was performed, e.g. 'Direct read of statute text on official legislature site'"
    },
    "pending_legislation": {
      "type": "array",
      "description": "Bills that would change any field if enacted. Flag, do not incorporate.",
      "items": {
        "$ref": "#/$defs/pendingItem"
      }
    },
    "security_deposits": {
      "type": "object",
      "required": [
        "max_deposit",
        "return_deadline_days",
        "itemization_required",
        "citations",
        "summary_plain"
      ],
      "properties": {
        "max_deposit": {
          "type": [
            "object",
            "null"
          ],
          "description": "null means no statutory cap — say so in notes",
          "properties": {
            "months_rent": {
              "type": [
                "number",
                "null"
              ]
            },
            "conditions": {
              "type": [
                "string",
                "null"
              ],
              "description": "e.g. cap differs for furnished units or senior tenants"
            }
          }
        },
        "return_deadline_days": {
          "type": [
            "integer",
            "null"
          ]
        },
        "return_deadline_conditions": {
          "type": [
            "string",
            "null"
          ],
          "description": "e.g. clock starts at move-out vs. receipt of forwarding address"
        },
        "itemization_required": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "itemization_rules": {
          "type": [
            "string",
            "null"
          ]
        },
        "separate_account_required": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "interest_required": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "interest_rules": {
          "type": [
            "string",
            "null"
          ]
        },
        "pet_deposit_rules": {
          "type": [
            "string",
            "null"
          ]
        },
        "nonrefundable_fees_allowed": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "penalty_for_violation": {
          "type": [
            "string",
            "null"
          ],
          "description": "e.g. 'double the amount wrongfully withheld'"
        },
        "tenant_forwarding_address_duty": {
          "type": [
            "string",
            "null"
          ]
        },
        "citations": {
          "$ref": "#/$defs/citations"
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "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). Preferred: array of {label, text} bullets, label bolded on-page. Legacy: single string. Operator bookkeeping goes in CHANGELOG-DATA.md, never here."
        }
      }
    },
    "rent_increase_notice": {
      "type": "object",
      "required": [
        "notice_days_month_to_month",
        "rent_control_state",
        "rent_regulation_preemption",
        "citations",
        "summary_plain"
      ],
      "properties": {
        "notice_days_month_to_month": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Days of notice required for m2m tenancy. null = no statutory requirement beyond termination notice"
        },
        "notice_varies_by_increase_size": {
          "type": [
            "string",
            "null"
          ],
          "description": "e.g. longer notice for increases over 10%"
        },
        "fixed_term_rules": {
          "type": [
            "string",
            "null"
          ]
        },
        "rent_control_state": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "true if statewide rent control/stabilization exists"
        },
        "rent_control_details": {
          "type": [
            "string",
            "null"
          ]
        },
        "local_control_preempted": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "Simplified yes/no view of rent_regulation_preemption.posture, kept for continuity: preempted = true, not_preempted = false, no_express_statute = null. The rent_regulation_preemption object is authoritative — its posture_qualifier carries the nuance a boolean cannot (e.g. Texas's disaster-only authorization)."
        },
        "rent_regulation_preemption": {
          "type": "object",
          "description": "Whether state law preempts local rent regulation (rent control/stabilization) — the statewide posture behind local_control_preempted, stated with a pinpoint citation and its own verification date. Postures: preempted = a statute expressly bars local rent regulation; not_preempted = local regulation is permitted, expressly authorized, or available through a statutory pathway; no_express_statute = no statute addresses the question and no ban is inferred from silence.",
          "required": [
            "topic_verified",
            "posture",
            "posture_qualifier",
            "citations",
            "summary_plain"
          ],
          "properties": {
            "topic_verified": {
              "type": "string",
              "format": "date",
              "description": "Date this posture was verified against official sources. Only set by an actual verification."
            },
            "posture": {
              "enum": [
                "preempted",
                "not_preempted",
                "no_express_statute"
              ]
            },
            "posture_qualifier": {
              "enum": [
                "conditional_authorization",
                "field_preemption",
                "voter_approval_exception",
                "legislative_approval_exception",
                "statewide_rent_cap",
                "savings_clause_only",
                null
              ],
              "description": "The wrinkle a bare posture would flatten: conditional_authorization = rent control allowed only through an extraordinary statutory pathway (TX: disaster + governor approval); field_preemption = no rent-specific bar, but a statute supersedes all local landlord-tenant ordinances (VA); voter_approval_exception = barred unless voters approve it (MN); legislative_approval_exception = barred unless the legislature approves (IN, MS, UT); statewide_rent_cap = a statewide cap coexists with the posture (WA, OR, CA); savings_clause_only = nothing bars local regulation, but the only statute on point merely preserves emergency ordinances (HI)."
            },
            "citations": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/citations/items"
              },
              "description": "Empty only when posture is no_express_statute (there is no statute to cite; the search basis lives in verified_by_method territory, not the record)."
            },
            "summary_plain": {
              "$ref": "#/$defs/summary_plain"
            },
            "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. Same shape as topic notes."
            }
          },
          "if": {
            "properties": {
              "posture": {
                "enum": [
                  "preempted",
                  "not_preempted"
                ]
              }
            }
          },
          "then": {
            "properties": {
              "citations": {
                "minItems": 1
              }
            }
          }
        },
        "frequency_limits": {
          "type": [
            "string",
            "null"
          ]
        },
        "citations": {
          "$ref": "#/$defs/citations"
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "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). Preferred: array of {label, text} bullets, label bolded on-page. Legacy: single string. Operator bookkeeping goes in CHANGELOG-DATA.md, never here."
        }
      }
    },
    "late_fees": {
      "type": "object",
      "required": [
        "statutory_cap",
        "grace_period_days",
        "citations",
        "summary_plain"
      ],
      "properties": {
        "statutory_cap": {
          "type": [
            "string",
            "null"
          ],
          "description": "e.g. '5% of monthly rent' or null = no statutory cap (reasonableness standard may apply — use notes)"
        },
        "grace_period_days": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Statutorily mandated grace period. null = none mandated"
        },
        "must_be_in_lease": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "daily_fees_allowed": {
          "type": [
            "string",
            "null"
          ]
        },
        "reasonableness_standard": {
          "type": [
            "string",
            "null"
          ],
          "description": "Case law or statutory reasonableness language where no hard cap exists"
        },
        "citations": {
          "$ref": "#/$defs/citations"
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "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). Preferred: array of {label, text} bullets, label bolded on-page. Legacy: single string. Operator bookkeeping goes in CHANGELOG-DATA.md, never here."
        }
      }
    },
    "entry_notice": {
      "type": "object",
      "required": [
        "notice_hours",
        "citations",
        "summary_plain"
      ],
      "properties": {
        "notice_hours": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Required advance notice in hours. null = no statutory requirement ('reasonable notice' states use notes)"
        },
        "notice_standard": {
          "type": [
            "string",
            "null"
          ],
          "description": "e.g. 'reasonable notice' where no fixed period"
        },
        "permitted_reasons": {
          "type": [
            "string",
            "null"
          ]
        },
        "emergency_exception": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "time_of_day_restrictions": {
          "type": [
            "string",
            "null"
          ]
        },
        "citations": {
          "$ref": "#/$defs/citations"
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "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). Preferred: array of {label, text} bullets, label bolded on-page. Legacy: single string. Operator bookkeeping goes in CHANGELOG-DATA.md, never here."
        }
      }
    },
    "eviction_process": {
      "type": "object",
      "required": [
        "notice_nonpayment_days",
        "self_help_prohibited",
        "citations",
        "summary_plain",
        "topic_verified"
      ],
      "properties": {
        "topic_verified": {
          "type": "string",
          "format": "date",
          "description": "Date this topic was verified against official sources. Exists because eviction_process is added to records whose record-level last_verified covers only the v1 topics. Only set by an actual verification."
        },
        "notice_nonpayment_days": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Days in the pay-or-quit notice for nonpayment of rent. null = no pre-filing notice statutorily required (explain in notes)"
        },
        "notice_nonpayment_rules": {
          "type": [
            "string",
            "null"
          ],
          "description": "Counting rules (calendar vs judicial days), cure rights and how late the tenant can cure, delivery/service methods"
        },
        "notice_lease_violation_days": {
          "type": [
            "integer",
            "null"
          ],
          "description": "The statutory pre-filing notice period for a lease violation, curable or not (e.g. WY's single notice to quit carries no cure right) — expressed as the notice's TERMINATION DATE (the day the landlord may first file) in most states, or as the notice period itself where the instrument is expressly non-terminating (e.g. ND's notice of intention to evict). Where a statute sets both a cure deadline and a termination date, encode the termination date and put both figures in the rules field. null is reserved for NO statutory period existing at all — never for filing mechanics (batch 5+7 convention; see the batch-7 METHOD.md)"
        },
        "notice_lease_violation_rules": {
          "type": [
            "string",
            "null"
          ],
          "description": "Cure vs quit split, what counts as material noncompliance, repeat-violation escalation"
        },
        "unconditional_quit_grounds": {
          "type": [
            "string",
            "null"
          ],
          "description": "Grounds allowing immediate/unconditional termination (illegal activity, irreparable breach, repeat violations) and the notice period attached"
        },
        "court_and_action": {
          "type": [
            "string",
            "null"
          ],
          "description": "Court that hears evictions, the action's statutory name (unlawful/forcible detainer, summary process, dispossessory), governing procedural rules"
        },
        "filing_to_hearing": {
          "type": [
            "string",
            "null"
          ],
          "description": "Statutory window between filing/service and the hearing or answer deadline"
        },
        "writ_and_lockout": {
          "type": [
            "string",
            "null"
          ],
          "description": "Name of the possession writ, earliest issuance after judgment, execution/lockout timing"
        },
        "appeal_window_days": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Days after judgment to appeal. null = standard civil appeal window applies (use notes)"
        },
        "timeline_uncontested": {
          "type": [
            "string",
            "null"
          ],
          "description": "Best-case notice-to-lockout span DERIVED from the statutory minimums cited in this record — present as a derivation, never as a promise; contested cases run longer"
        },
        "self_help_prohibited": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "true if landlord self-help (lockout, utility shutoff) is statutorily barred"
        },
        "self_help_rules": {
          "type": [
            "string",
            "null"
          ],
          "description": "The self-help statute's scope and tenant remedies/penalties"
        },
        "citations": {
          "$ref": "#/$defs/citations"
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "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). Preferred: array of {label, text} bullets, label bolded on-page. Legacy: single string. Operator bookkeeping goes in CHANGELOG-DATA.md, never here."
        }
      }
    },
    "application_screening_fees": {
      "type": "object",
      "description": "Seventh topic (D-059 topic #7, build started 2026-08-25): rental application and tenant-screening fees — what a landlord may charge an applicant, and the receipt, refund, disclosure, adverse-action, reusable-report, holding-deposit, fee-transparency, and penalty rules that ride with the charge. OPTIONAL while the 50-state build is in progress (mobile_home_parks precedent); flips to required at 50/50. Simple topic shape (late_fees pattern): a null field is a verified statutory absence whose meaning renders via the field's nullLabel in src/lib/topics.js, with the basis carried in notes where reader-relevant. A rule enacted but not yet in force is stated in the field's text with its date AND flagged as a typed pending_legislation entry (lifecycle signed + effective_on) so incorporation is machine-scheduled. Citations are official sources only; the validator rejects official=false in this topic.",
      "required": [
        "topic_verified",
        "verified_by_method",
        "application_fee_cap",
        "fee_limited_to_actual_cost",
        "screening_fee_rules",
        "receipt_required",
        "refund_required",
        "refund_rules",
        "disclosure_rules",
        "adverse_action_rules",
        "reusable_report_rules",
        "holding_deposit_rules",
        "junk_fee_limits",
        "penalty_for_violation",
        "citations",
        "summary_plain",
        "notes"
      ],
      "additionalProperties": false,
      "properties": {
        "topic_verified": {
          "type": "string",
          "format": "date",
          "description": "Date this topic was verified against official sources. Only set by an actual verification."
        },
        "verified_by_method": {
          "type": "string",
          "description": "How verification was performed for this topic (sources read). The one field in the topic allowed to carry method register."
        },
        "application_fee_cap": {
          "$ref": "#/$defs/asfString",
          "description": "The headline instrument, never a bare yes/no: flat dollar cap, greater-of formula, actual-cost limit, indexed cap (with the current published figure, where published, and its as-of date), or a ban / enumerated-charges regime. null = no statutory cap on application fees."
        },
        "fee_limited_to_actual_cost": {
          "$ref": "#/$defs/asfBool",
          "description": "true only where a statute ties the fee to the actual cost of screening/reports. null = no such statute."
        },
        "screening_fee_rules": {
          "$ref": "#/$defs/asfString",
          "description": "Conditions on screening charges beyond a bare cap: who may charge, one-per-applicant rules, must-use-the-report rules, notice or agreement prerequisites, vacancy prerequisites. null = no statute governs screening charges separately."
        },
        "receipt_required": {
          "$ref": "#/$defs/asfBool",
          "description": "Statutory receipt duty for application/screening money. null = none."
        },
        "refund_required": {
          "$ref": "#/$defs/asfBool",
          "description": "true if at least one statutory circumstance forces return of some or all of the fee. null = none."
        },
        "refund_rules": {
          "$ref": "#/$defs/asfString",
          "description": "When and how much must come back: not screened, unit unavailable, excess over actual cost, applicant withdraws; deadlines and mechanics. null = no statutory refund duty."
        },
        "disclosure_rules": {
          "$ref": "#/$defs/asfString",
          "description": "What must be told the applicant BEFORE collecting: criteria, fee basis, applicant rights. null = no statutory disclosure duty."
        },
        "adverse_action_rules": {
          "$ref": "#/$defs/asfString",
          "description": "STATE-level denial-notice duties only; federal fair-credit duties are context, never the value. null = no state statute."
        },
        "reusable_report_rules": {
          "$ref": "#/$defs/asfString",
          "description": "Portable/reusable screening-report regime: must accept? no fee when used? validity window. null = no statute on reusable screening reports."
        },
        "holding_deposit_rules": {
          "$ref": "#/$defs/asfString",
          "description": "Fees/deposits to hold a unit pending the lease: caps, written-statement duties, disposition on each outcome. null = no statute on holding deposits."
        },
        "junk_fee_limits": {
          "$ref": "#/$defs/asfString",
          "description": "Rental fee-transparency rules as they reach residential rental advertising and application-stage fees (all-in advertised price, mandatory-fee itemization, hidden-fee bans) — statutes or duly adopted state regulations. null = no rental fee-transparency rule."
        },
        "penalty_for_violation": {
          "$ref": "#/$defs/asfString",
          "description": "Statutory damages/penalties for violating any of the above, named duty by duty. null = no specific statutory penalty."
        },
        "pending_legislation": {
          "type": "array",
          "description": "Bills that would change any field if enacted, plus signed acts with future effective dates. Flag, do not incorporate.",
          "items": {
            "$ref": "#/$defs/pendingItem"
          }
        },
        "citations": {
          "$ref": "#/$defs/citations"
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "notes": {
          "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). Array of {label, text} bullets; carries the reader-relevant basis for every null field."
        }
      }
    },
    "mobile_home_parks": {
      "type": "object",
      "description": "Sixth topic (D-058, build started 2026-08-18): manufactured-home / mobile-home community lot tenancies — the community owner vs. a resident who owns the home and rents the lot. OPTIONAL while the 50-state build is in progress (eviction_process precedent); flips to required at 50/50. Every field in `fields` is a status cell: regulated (value + citation), not_regulated (a verified absence with the section that would carry it or the act's scope section as its citation), not_researched (build-failing). Field keys and value types are defined in src/lib/mhp.js and enforced by scripts/validate-data.mjs. Citations are official sources only (state legislature / agency / session law); the validator rejects any citation with official=false in this topic.",
      "required": [
        "topic_verified",
        "verified_by_method",
        "tier",
        "act_name",
        "act_citation",
        "fields",
        "fhfa_protections",
        "citations",
        "summary_plain"
      ],
      "additionalProperties": false,
      "properties": {
        "topic_verified": {
          "type": "string",
          "format": "date",
          "description": "Date this topic was verified against official sources. Only set by an actual verification."
        },
        "verified_by_method": {
          "type": "string",
          "description": "How verification was performed for this topic (sources read). The one field in the topic allowed to carry method register."
        },
        "tier": {
          "enum": [
            1,
            2,
            3,
            4
          ],
          "description": "1 = dedicated act + a named agency with a role in the tenancy + active legislation; 2 = free-standing act, thin or no institution; 3 = park rules embedded in general law or a single targeted section; 4 = no manufactured-home tenancy act (general landlord-tenant law, cited as fallback_act, or nothing)."
        },
        "act_name": {
          "type": [
            "string",
            "null"
          ],
          "description": "Popular or official name of the state's manufactured-home tenancy act. null only for tier 4."
        },
        "act_citation": {
          "type": [
            "string",
            "null"
          ],
          "description": "Chapter/article citation of the act, e.g. 'ORS 90.505–90.850'. null only for tier 4."
        },
        "fallback_act": {
          "type": [
            "string",
            "null"
          ],
          "description": "For tier 3–4: the general landlord-tenant act (or nothing) that governs a lot tenancy, stated so that statutory silence is never read as permission."
        },
        "fields": {
          "type": "object",
          "description": "One status cell per key in src/lib/mhp.js MHP_FIELDS (all keys required; the validator enforces the full set).",
          "additionalProperties": {
            "$ref": "#/$defs/mhpCell"
          }
        },
        "fhfa_protections": {
          "type": "object",
          "description": "The state's law mapped onto the eight GSE Tenant Site Lease Protections (FHFA Duty to Serve). meets = true only where a state statute requires the protection of every covered community; 'partial' where the statute grants a weaker or narrower version; false where state law is silent or contrary. basis is the plain sentence stating which rule satisfies or fails the cell.",
          "required": [
            "p1",
            "p2",
            "p3",
            "p4",
            "p5",
            "p6",
            "p7",
            "p8"
          ],
          "additionalProperties": false,
          "properties": {
            "p1": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p2": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p3": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p4": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p5": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p6": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p7": {
              "$ref": "#/$defs/fhfaCell"
            },
            "p8": {
              "$ref": "#/$defs/fhfaCell"
            }
          }
        },
        "pending_legislation": {
          "type": "array",
          "description": "Bills that would change any cell if enacted. Flag, do not incorporate.",
          "items": {
            "$ref": "#/$defs/pendingItem"
          }
        },
        "citations": {
          "$ref": "#/$defs/citations",
          "description": "The act itself (definitions/scope section first) and any agency page cited in the summary."
        },
        "summary_plain": {
          "$ref": "#/$defs/summary_plain"
        },
        "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). Preferred: array of {label, text} bullets."
        }
      }
    }
  },
  "$defs": {
    "asfString": {
      "type": [
        "string",
        "null"
      ]
    },
    "asfBool": {
      "type": [
        "boolean",
        "null"
      ]
    },
    "pendingItem": {
      "type": "object",
      "required": [
        "bill",
        "summary",
        "status",
        "checked",
        "lifecycle",
        "signed_on",
        "effective_on"
      ],
      "additionalProperties": false,
      "properties": {
        "bill": {
          "type": "string"
        },
        "summary": {
          "type": "string"
        },
        "status": {
          "type": "string",
          "description": "Plain-language account of where the measure stands, from the official legislative record as of `checked`."
        },
        "checked": {
          "type": "string",
          "format": "date"
        },
        "lifecycle": {
          "enum": [
            "introduced",
            "passed_one_chamber",
            "passed_both_chambers",
            "signed",
            "vetoed",
            "dead",
            "none_pending"
          ],
          "description": "Stage of the measure as of `checked`: introduced (filed or in committee), passed_one_chamber, passed_both_chambers (awaiting executive action), signed (enacted; see effective_on for when the flagged change operates), vetoed, dead (failed, expired with its session, or postponed indefinitely), none_pending (a verified statement that no qualifying measure is pending)."
        },
        "signed_on": {
          "type": [
            "string",
            "null"
          ],
          "format": "date",
          "description": "Date the measure was signed or enacted, where the official record states one; null otherwise."
        },
        "effective_on": {
          "type": [
            "string",
            "null"
          ],
          "format": "date",
          "description": "Date the change this entry flags becomes operative law, where known; null otherwise. When this date arrives, the change is incorporated into the record's answers and the flag is cleared."
        }
      }
    },
    "mhpCell": {
      "type": "object",
      "required": [
        "status",
        "value",
        "citations"
      ],
      "additionalProperties": false,
      "properties": {
        "status": {
          "enum": [
            "regulated",
            "not_regulated",
            "not_researched"
          ]
        },
        "value": {
          "description": "Typed per src/lib/mhp.js; must be null unless status is regulated."
        },
        "detail": {
          "type": [
            "string",
            "null"
          ],
          "description": "Plain sentence qualifying the value: day-counting, thresholds, exemptions, or — for not_regulated — what governs instead (lease terms, general law)."
        },
        "citations": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/citations/items"
          }
        },
        "effective_from": {
          "type": [
            "string",
            "null"
          ],
          "format": "date",
          "description": "Set when the value states a rule enacted but not yet in force on topic_verified; the page shows the current rule in detail and the pending one as dated."
        },
        "sub_state_variation": {
          "type": [
            "string",
            "null"
          ],
          "description": "Set when the rule applies only in part of the state (e.g. counties above a population threshold, jurisdictions that adopted a uniform act)."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "status": {
                "const": "regulated"
              }
            }
          },
          "then": {
            "properties": {
              "value": {
                "not": {
                  "type": "null"
                }
              },
              "citations": {
                "minItems": 1
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "status": {
                "const": "not_regulated"
              }
            }
          },
          "then": {
            "properties": {
              "value": {
                "type": "null"
              },
              "citations": {
                "minItems": 1
              }
            }
          }
        }
      ]
    },
    "fhfaCell": {
      "type": "object",
      "required": [
        "meets",
        "basis",
        "citations"
      ],
      "additionalProperties": false,
      "properties": {
        "meets": {
          "enum": [
            true,
            false,
            "partial"
          ]
        },
        "basis": {
          "type": "string",
          "minLength": 20
        },
        "citations": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/citations/items"
          }
        }
      },
      "if": {
        "properties": {
          "meets": {
            "enum": [
              true,
              "partial"
            ]
          }
        }
      },
      "then": {
        "properties": {
          "citations": {
            "minItems": 1
          }
        }
      }
    },
    "citations": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": [
          "statute",
          "url",
          "official"
        ],
        "properties": {
          "statute": {
            "type": "string",
            "description": "e.g. 'MCL 554.602'"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Link to the statute on the official state legislature site whenever one exists"
          },
          "official": {
            "type": "boolean",
            "description": "true only for state-government sources"
          },
          "pinpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "Subsection, e.g. '(1)(a)'"
          }
        }
      }
    },
    "summary_plain": {
      "type": "string",
      "minLength": 100,
      "description": "Plain-language summary written specifically for this state. The first sentence must be the quotable answer-box sentence."
    }
  }
}