{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://1001smartcities.org/schemas/evidence-passport.schema.json",
  "title": "1001 Smart Cities Evidence Passport",
  "description": "Append-only, claim-addressable evidence records for projects, cities, countries, glossary terms and topics.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schemaVersion", "constitutionVersion", "createdAt", "description", "entities"],
  "properties": {
    "schemaVersion": { "const": "1.0.0" },
    "constitutionVersion": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
    "createdAt": { "$ref": "#/$defs/dateTime" },
    "description": { "type": "string", "minLength": 1 },
    "entities": {
      "type": "array",
      "items": { "$ref": "#/$defs/entityRecord" }
    }
  },
  "$defs": {
    "date": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
    },
    "dateTime": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
    },
    "nullableDate": {
      "oneOf": [
        { "$ref": "#/$defs/date" },
        { "type": "null" }
      ]
    },
    "nullableString": {
      "type": ["string", "null"]
    },
    "entity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "id", "title", "canonicalUrl"],
      "properties": {
        "type": {
          "enum": ["project", "city", "country", "glossary", "topic"]
        },
        "id": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]*$"
        },
        "title": { "type": "string", "minLength": 1 },
        "canonicalUrl": { "type": "string", "format": "uri", "pattern": "^https://" }
      }
    },
    "entityRecord": {
      "type": "object",
      "additionalProperties": false,
      "required": ["entity", "currentRevisionId", "revisions"],
      "properties": {
        "entity": { "$ref": "#/$defs/entity" },
        "currentRevisionId": { "$ref": "#/$defs/revisionId" },
        "revisions": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/revision" }
        }
      }
    },
    "revisionId": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]*$"
    },
    "preparedBy": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "label", "humanApproved"],
      "properties": {
        "type": { "enum": ["automation", "human"] },
        "label": { "type": "string", "minLength": 1 },
        "humanApproved": { "type": "boolean" }
      }
    },
    "review": {
      "type": "object",
      "additionalProperties": false,
      "required": ["status", "by", "date", "note"],
      "properties": {
        "status": {
          "enum": ["unreviewed", "machine-validated", "human-reviewed", "expert-reviewed"]
        },
        "by": { "$ref": "#/$defs/nullableString" },
        "date": {
          "oneOf": [
            { "$ref": "#/$defs/date" },
            { "type": "null" }
          ]
        },
        "note": { "$ref": "#/$defs/nullableString" }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "status": { "enum": ["human-reviewed", "expert-reviewed"] }
            }
          },
          "then": {
            "properties": {
              "by": { "type": "string", "minLength": 1 },
              "date": { "$ref": "#/$defs/date" }
            }
          }
        }
      ]
    },
    "change": {
      "type": "object",
      "additionalProperties": false,
      "required": ["operation", "path", "summary"],
      "properties": {
        "operation": { "enum": ["add", "replace", "remove", "retract"] },
        "path": { "type": "string", "pattern": "^/" },
        "summary": { "type": "string", "minLength": 1 }
      }
    },
    "revision": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "createdAt",
        "effectiveAt",
        "changeType",
        "summary",
        "preparedBy",
        "review",
        "changes",
        "snapshotHash",
        "snapshot"
      ],
      "properties": {
        "id": { "$ref": "#/$defs/revisionId" },
        "createdAt": { "$ref": "#/$defs/dateTime" },
        "effectiveAt": { "$ref": "#/$defs/date" },
        "changeType": { "enum": ["baseline", "correction", "update", "reclassification", "retraction"] },
        "summary": { "type": "string", "minLength": 1 },
        "preparedBy": { "$ref": "#/$defs/preparedBy" },
        "review": { "$ref": "#/$defs/review" },
        "changes": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/change" }
        },
        "snapshotHash": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
        "snapshot": { "$ref": "#/$defs/snapshot" }
      }
    },
    "assurance": {
      "type": "object",
      "additionalProperties": false,
      "required": ["status", "scope", "statement", "machineChecks"],
      "properties": {
        "status": {
          "enum": ["unreviewed", "machine-validated", "human-reviewed", "expert-reviewed"]
        },
        "scope": { "type": "string", "minLength": 1 },
        "statement": { "type": "string", "minLength": 1 },
        "machineChecks": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "minLength": 1 }
        }
      }
    },
    "projectState": {
      "type": "object",
      "additionalProperties": false,
      "required": ["status", "outcome", "evidenceGrade", "timeline"],
      "properties": {
        "status": { "$ref": "#/$defs/nullableString" },
        "outcome": { "$ref": "#/$defs/nullableString" },
        "evidenceGrade": { "$ref": "#/$defs/nullableString" },
        "timeline": {
          "type": "object",
          "additionalProperties": false,
          "required": ["started", "ended"],
          "properties": {
            "started": { "type": ["integer", "null"] },
            "ended": { "type": ["integer", "null"] }
          }
        }
      }
    },
    "governance": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "operator",
        "actorTypes",
        "fundingModel",
        "fundingDescription",
        "cost",
        "ownership",
        "decisionRights",
        "exitConditions"
      ],
      "properties": {
        "operator": { "$ref": "#/$defs/nullableString" },
        "actorTypes": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
        "fundingModel": { "$ref": "#/$defs/nullableString" },
        "fundingDescription": { "$ref": "#/$defs/nullableString" },
        "cost": { "$ref": "#/$defs/nullableString" },
        "ownership": { "$ref": "#/$defs/nullableString" },
        "decisionRights": { "$ref": "#/$defs/nullableString" },
        "exitConditions": { "$ref": "#/$defs/nullableString" }
      }
    },
    "claim": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "field",
        "text",
        "statementKind",
        "textMode",
        "mappingStatus",
        "sourceRefs",
        "supportNote",
        "caveat",
        "interpretation"
      ],
      "properties": {
        "id": { "type": "string", "pattern": "^clm-[a-f0-9]{16}$" },
        "field": { "enum": ["snippet", "impact", "lesson", "body", "definition", "summary"] },
        "text": { "type": "string", "minLength": 1 },
        "statementKind": { "enum": ["descriptive", "quantitative", "causal", "evaluative"] },
        "textMode": { "enum": ["verbatim-from-project-record", "verbatim-from-story-page", "quoted", "normalised", "derived"] },
        "mappingStatus": { "enum": ["mapped", "partially-mapped", "unmapped", "disputed"] },
        "sourceRefs": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": { "type": "string", "pattern": "^src-[a-f0-9]{16}$" }
        },
        "supportNote": { "$ref": "#/$defs/nullableString" },
        "caveat": { "$ref": "#/$defs/nullableString" },
        "interpretation": {
          "type": "object",
          "additionalProperties": false,
          "required": ["added", "interpolation", "note"],
          "properties": {
            "added": { "type": "boolean" },
            "interpolation": { "type": "boolean" },
            "note": { "type": "string", "minLength": 1 }
          }
        }
      }
    },
    "publisher": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "domain", "classification"],
      "properties": {
        "name": { "$ref": "#/$defs/nullableString" },
        "domain": { "type": "string", "minLength": 1 },
        "classification": {
          "enum": ["not-classified", "operator", "government", "regulator", "audit", "research", "media", "civil-society", "vendor", "reference"]
        }
      }
    },
    "temporal": {
      "type": "object",
      "additionalProperties": false,
      "required": ["publishedAt", "updatedAt", "sourceCheckedAt", "recordLastVerifiedAt", "dossierCreatedAt", "retrievedAt", "status"],
      "properties": {
        "publishedAt": { "$ref": "#/$defs/nullableDate" },
        "updatedAt": { "$ref": "#/$defs/nullableDate" },
        "sourceCheckedAt": { "$ref": "#/$defs/nullableDate" },
        "recordLastVerifiedAt": { "$ref": "#/$defs/date" },
        "dossierCreatedAt": { "$ref": "#/$defs/date" },
        "retrievedAt": { "$ref": "#/$defs/nullableDate" },
        "status": { "enum": ["publication-and-record-dates-recorded", "record-date-only", "undated"] }
      }
    },
    "locator": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "value", "exact"],
      "properties": {
        "type": { "enum": ["page", "section", "paragraph", "timestamp", "dataset-row", "descriptive-source-note", "not-recorded"] },
        "value": { "$ref": "#/$defs/nullableString" },
        "exact": { "type": "boolean" }
      }
    },
    "preservation": {
      "type": "object",
      "additionalProperties": false,
      "required": ["archiveUrl", "archivedAt", "contentHash", "status"],
      "properties": {
        "archiveUrl": { "$ref": "#/$defs/nullableString" },
        "archivedAt": { "$ref": "#/$defs/nullableString" },
        "contentHash": { "$ref": "#/$defs/nullableString" },
        "status": { "enum": ["archive-linked", "content-captured", "not-captured", "capture-failed"] }
      }
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "title",
        "url",
        "publisher",
        "sourceType",
        "language",
        "role",
        "claimRefs",
        "temporal",
        "locator",
        "preservation"
      ],
      "properties": {
        "id": { "type": "string", "pattern": "^src-[a-f0-9]{16}$" },
        "title": { "type": "string", "minLength": 1 },
        "url": { "type": "string", "format": "uri" },
        "publisher": { "$ref": "#/$defs/publisher" },
        "sourceType": { "enum": ["web-page", "pdf", "dataset", "legal-document", "video", "other"] },
        "language": { "type": "string", "minLength": 2 },
        "role": { "enum": ["claim-evidence", "background", "contradiction", "context"] },
        "claimRefs": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "pattern": "^clm-[a-f0-9]{16}$" }
        },
        "temporal": { "$ref": "#/$defs/temporal" },
        "locator": { "$ref": "#/$defs/locator" },
        "preservation": { "$ref": "#/$defs/preservation" }
      }
    },
    "coverage": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "claimsTotal",
        "claimsMapped",
        "sourcesTotal",
        "sourcesUsedByClaims",
        "sourcesWithPublicationDate",
        "sourcesWithArchive",
        "sourcesWithExactLocator",
        "sourcesWithContentHash"
      ],
      "properties": {
        "claimsTotal": { "type": "integer", "minimum": 0 },
        "claimsMapped": { "type": "integer", "minimum": 0 },
        "sourcesTotal": { "type": "integer", "minimum": 0 },
        "sourcesUsedByClaims": { "type": "integer", "minimum": 0 },
        "sourcesWithPublicationDate": { "type": "integer", "minimum": 0 },
        "sourcesWithArchive": { "type": "integer", "minimum": 0 },
        "sourcesWithExactLocator": { "type": "integer", "minimum": 0 },
        "sourcesWithContentHash": { "type": "integer", "minimum": 0 }
      }
    },
    "snapshot": {
      "type": "object",
      "additionalProperties": false,
      "required": ["asOf", "assurance", "governance", "claims", "sources", "coverage", "limits"],
      "properties": {
        "asOf": { "$ref": "#/$defs/date" },
        "projectFingerprint": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
        "assurance": { "$ref": "#/$defs/assurance" },
        "projectState": { "$ref": "#/$defs/projectState" },
        "governance": { "$ref": "#/$defs/governance" },
        "claims": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/claim" }
        },
        "sources": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/source" }
        },
        "coverage": { "$ref": "#/$defs/coverage" },
        "limits": {
          "type": "array",
          "items": { "type": "string", "minLength": 1 }
        }
      }
    }
  }
}
