{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://aidisclose.io/schema/1.0.0/ai-disclosure.schema.json",
  "title": "ai-disclosure.json v1.0.0",
  "type": "object",
  "required": ["specVersion", "publisher", "lastUpdated", "languages", "aiSystems"],
  "additionalProperties": false,
  "patternProperties": { "^x-": {} },
  "allOf": [
    {
      "if": { "properties": { "noAiDeclared": { "const": true } }, "required": ["noAiDeclared"] },
      "then": { "properties": { "aiSystems": { "type": "array", "maxItems": 0 } } },
      "else": { "required": ["evidence"] }
    }
  ],
  "$defs": {
    "bcp47": { "type": "string", "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$" },
    "slug": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]{0,63}$" },
    "httpsUrl": { "type": "string", "pattern": "^https://[^\\s]+$" },
    "openEnum": {
      "description": "Known values are enumerated for tooling; any other non-empty string is tolerated so new values ship without a breaking schema change. Readers treat unknown values as opaque.",
      "type": "string",
      "minLength": 1
    },
    "editorialResponsibility": {
      "type": "object",
      "additionalProperties": false,
      "patternProperties": { "^x-": {} },
      "properties": {
        "humanReview": { "type": "boolean" },
        "statementUrl": { "$ref": "#/$defs/httpsUrl" }
      }
    }
  },
  "properties": {
    "$schema": { "type": "string" },
    "specVersion": {
      "description": "Major.minor.patch of the spec. Validated by major only (^1.) so a reader accepts any compatible 1.x manifest.",
      "type": "string",
      "pattern": "^1\\."
    },
    "publisher": {
      "type": "object",
      "required": ["name", "domain", "contact"],
      "additionalProperties": false,
      "patternProperties": { "^x-": {} },
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "legalName": { "type": "string" },
        "domain": { "type": "string", "pattern": "^[a-z0-9.-]+\\.[a-z]{2,}$" },
        "contact": {
          "description": "A reachable contact: a mailto: email or an https URL.",
          "type": "string",
          "pattern": "^(mailto:[^\\s@]+@[^\\s@]+\\.[^\\s@]+|https://[^\\s]+)$"
        },
        "euRepresentative": { "type": "string" }
      }
    },
    "lastUpdated": {
      "description": "Full-date, YYYY-MM-DD.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "languages": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bcp47" } },
    "noAiDeclared": {
      "type": "boolean",
      "description": "Publisher declares that the site operates no AI systems and publishes no content generated by AI. Requires aiSystems to be empty and makes evidence optional. Renders the Made by humans badge."
    },
    "aiSystems": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "name", "role", "kind", "purpose", "disclosure"],
        "additionalProperties": false,
        "patternProperties": { "^x-": {} },
        "properties": {
          "id": {
            "description": "Unique slug within this manifest.",
            "$ref": "#/$defs/slug"
          },
          "name": { "type": "string" },
          "role": { "enum": ["provider", "deployer", "both"] },
          "kind": {
            "description": "Known: conversational | content-generation | emotion-recognition | biometric-categorisation | other.",
            "$ref": "#/$defs/openEnum"
          },
          "vendor": { "type": "string" },
          "model": { "type": "string" },
          "purpose": { "type": "string" },
          "obligations": {
            "description": "Disclosure obligations by jurisdiction. jurisdiction and provision ids match the AIDisclose registry (e.g. eu, us-ca).",
            "type": "array",
            "items": {
              "type": "object",
              "required": ["jurisdiction"],
              "additionalProperties": false,
              "patternProperties": { "^x-": {} },
              "properties": {
                "jurisdiction": { "type": "string", "pattern": "^[a-z][a-z0-9-]{0,31}$" },
                "provisions": {
                  "type": "array",
                  "uniqueItems": true,
                  "items": { "$ref": "#/$defs/slug" }
                },
                "params": {
                  "description": "Optional structured parameters for this obligation (e.g. reDisclosureHours, takedownWindowHours, monthlyUserThreshold, toolUrl). Keys are obligation-specific and defined by the registry; unknown keys are tolerated so parameterized laws ship without a schema change.",
                  "type": "object"
                }
              }
            }
          },
          "disclosure": {
            "type": "object",
            "additionalProperties": false,
            "patternProperties": { "^x-": {} },
            "if": { "properties": { "scope": { "const": "page" } }, "required": ["scope"] },
            "then": { "required": ["pages"], "properties": { "pages": { "type": "array", "minItems": 1 } } },
            "properties": {
              "methods": {
                "description": "Optional, descriptive: how the disclosure is surfaced. Known: banner | inline-label | icon | audio-notice | metadata. `kind` and `scope` are what the reference tooling acts on.",
                "type": "array",
                "minItems": 1,
                "uniqueItems": true,
                "items": { "$ref": "#/$defs/openEnum" }
              },
              "scope": {
                "description": "Where the visible disclosure appears. site = a persistent site-wide notice; page = a notice only on URLs matching pages (which is then required); element = labels on [data-ai-content] elements.",
                "enum": ["site", "page", "element"]
              },
              "pages": {
                "description": "URL path globs the page-scope notice applies to, e.g. /blog/*. Required when scope is page.",
                "type": "array",
                "uniqueItems": true,
                "items": { "type": "string", "minLength": 1 }
              },
              "placement": { "type": "string" },
              "texts": {
                "type": "object",
                "$comment": "The BCP-47 key pattern is intentionally inlined here (it mirrors $defs/bcp47); a patternProperties key cannot $ref a string pattern. Keep the two patterns in sync.",
                "patternProperties": { "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$": { "type": "string" } },
                "additionalProperties": false
              }
            }
          },
          "editorialResponsibility": {
            "description": "Per-system human editorial review. When humanReview is true, AI content is published under editorial responsibility (the Article 50(4) text exemption basis). Overrides the manifest-level default.",
            "$ref": "#/$defs/editorialResponsibility"
          },
          "agentInteractionPolicy": {
            "description": "Known: always | when-plausible | n/a. always implements the EU Guidelines rule for agents where human interaction is plausible.",
            "$ref": "#/$defs/openEnum"
          },
          "generationDegree": {
            "description": "Degree of AI involvement. Known: fully-ai-generated | ai-assisted | manipulated | unspecified.",
            "$ref": "#/$defs/openEnum"
          },
          "mediaTypes": {
            "description": "Modalities this system produces or processes. Known: text | image | video | audio. Records the medium so the applicable Article 50 duties are unambiguous per modality (text disclosure under 50(4), synthetic-media marking under 50(2)).",
            "type": "array",
            "uniqueItems": true,
            "items": { "$ref": "#/$defs/openEnum" }
          },
          "publicInterest": {
            "description": "True when this system's AI-generated text informs the public on matters of public interest. Records the Article 50(4) text-disclosure condition for audit and downstream duty determination.",
            "type": "boolean"
          }
        }
      }
    },
    "contentMarking": {
      "type": "object",
      "additionalProperties": false,
      "patternProperties": { "^x-": {} },
      "properties": {
        "machineReadable": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["standard", "scope"],
            "additionalProperties": false,
            "patternProperties": { "^x-": {} },
            "properties": {
              "standard": {
                "description": "Known: C2PA | IPTC-DigitalSourceType | schema.org | watermark | other.",
                "$ref": "#/$defs/openEnum"
              },
              "scope": { "type": "string" },
              "detectionEndpoint": { "$ref": "#/$defs/httpsUrl" }
            }
          }
        },
        "visibleLabel": {
          "type": "object",
          "additionalProperties": false,
          "patternProperties": { "^x-": {} },
          "if": { "properties": { "style": { "const": "custom" } }, "required": ["style"] },
          "then": { "required": ["customLabel"] },
          "properties": {
            "style": { "enum": ["AI-acronym", "custom"] },
            "customLabel": { "type": "string" },
            "localized": { "type": "boolean" }
          }
        },
        "detectionToolUrl": {
          "description": "Public AI-detection tool the publisher makes available (e.g. California SB 942's free detection tool). Must be an https URL.",
          "$ref": "#/$defs/httpsUrl"
        }
      }
    },
    "editorialResponsibility": {
      "description": "Site-wide editorial-responsibility default; a system's own editorialResponsibility overrides it.",
      "$ref": "#/$defs/editorialResponsibility"
    },
    "evidence": {
      "type": "object",
      "required": ["retentionMonths"],
      "additionalProperties": false,
      "patternProperties": { "^x-": {} },
      "properties": {
        "retentionMonths": { "type": "integer", "minimum": 6 },
        "registerUrl": { "$ref": "#/$defs/httpsUrl" }
      }
    },
    "exemptions": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["systemId", "basis", "rationale"],
        "additionalProperties": false,
        "patternProperties": { "^x-": {} },
        "properties": {
          "systemId": {
            "description": "Must match an aiSystems[].id in this manifest.",
            "$ref": "#/$defs/slug"
          },
          "basis": {
            "description": "Known: obviousness | artistic | law-enforcement | editorial-review | other.",
            "$ref": "#/$defs/openEnum"
          },
          "rationale": { "type": "string" }
        }
      }
    }
  }
}
