{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "/schemas/3.1.0-beta.3/core/provenance.json",
  "title": "Provenance",
  "description": "Declares how content was produced, whether AI was involved, and what disclosure obligations apply. Attaches to creative manifests, individual assets, or content-standards artifacts. When present at multiple levels, the most specific provenance object replaces the inherited one entirely (no field-level merging). Provenance is a claim by the declaring party — receiving parties should verify claims independently via their own detection tools.",
  "type": "object",
  "properties": {
    "digital_source_type": {
      "$ref": "/schemas/3.1.0-beta.3/enums/digital-source-type.json",
      "description": "IPTC-aligned classification of AI involvement in producing this content"
    },
    "ai_tool": {
      "type": "object",
      "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.",
      "properties": {
        "name": {
          "type": "string",
          "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')"
        },
        "version": {
          "type": "string",
          "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version."
        },
        "provider": {
          "type": "string",
          "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')"
        }
      },
      "required": ["name"],
      "additionalProperties": true
    },
    "human_oversight": {
      "type": "string",
      "description": "Level of human involvement in the AI-assisted creation process. Independent of `disclosure.required` — the protocol does not derive disclosure obligations from oversight level. Some regulations include carve-outs for human-edited or human-directed AI output, but those carve-outs have factual prerequisites the schema cannot evaluate. Asserting `edited` or `directed` does not by itself justify `disclosure.required: false`.",
      "enum": [
        "none",
        "prompt_only",
        "selected",
        "edited",
        "directed"
      ],
      "enumDescriptions": {
        "none": "Fully automated with no human involvement in generation",
        "prompt_only": "Human provided the prompt or instructions but did not review outputs",
        "selected": "Human selected from multiple AI-generated candidates",
        "edited": "Human edited or refined AI-generated output",
        "directed": "Human directed the creative process with AI as an assistive tool"
      }
    },
    "declared_by": {
      "type": "object",
      "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.",
      "properties": {
        "agent_url": {
          "type": "string",
          "format": "uri",
          "description": "URL of the agent or service that declared this provenance"
        },
        "role": {
          "type": "string",
          "enum": ["creator", "advertiser", "agency", "platform", "tool"],
          "description": "Role of the declaring party in the supply chain",
          "enumDescriptions": {
            "creator": "The party that created or generated the content",
            "advertiser": "The brand or advertiser that owns the content",
            "agency": "Agency acting on behalf of the advertiser",
            "platform": "Ad platform or publisher that processed the content",
            "tool": "Automated tool or service that attached provenance metadata"
          }
        }
      },
      "required": ["role"],
      "additionalProperties": true
    },
    "declared_at": {
      "type": "string",
      "format": "date-time",
      "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance."
    },
    "created_time": {
      "type": "string",
      "format": "date-time",
      "description": "When this content was created or generated (ISO 8601)"
    },
    "c2pa": {
      "type": "object",
      "description": "C2PA sidecar manifest reference. Links to a detached cryptographic provenance manifest for this content. Note: file-level C2PA bindings break when ad servers transcode, resize, or re-encode assets. For pipelines with intermediaries, consider embedded_provenance as the primary provenance mechanism.",
      "properties": {
        "manifest_url": {
          "type": "string",
          "format": "uri",
          "description": "URL to the C2PA manifest store for this content"
        }
      },
      "required": ["manifest_url"],
      "additionalProperties": true
    },
    "embedded_provenance": {
      "type": "array",
      "description": "Provenance metadata embedded within the content stream. Each entry declares one embedding layer: structured provenance data carried inside the content itself, as distinct from sidecar references (c2pa.manifest_url). Embedded provenance survives operations that break sidecar and file-level bindings: ad-server transcoding, CMS ingestion, copy-paste, reformatting, and CDN re-encoding. For ad-tech pipelines where content passes through multiple intermediaries, embedded provenance is the reliable path for provenance that persists from declaration through delivery. This is a declaration by the embedding party. The receiving party (the seller) is the verifier-of-record: it confirms the claim by calling a governance agent it trusts (typically one published in `creative_policy.accepted_verifiers`).",
      "minItems": 1,
      "items": {
        "type": "object",
        "properties": {
          "method": {
            "$ref": "/schemas/3.1.0-beta.3/enums/embedded-provenance-method.json",
            "description": "How provenance data is carried within the content"
          },
          "standard": {
            "type": "string",
            "description": "Standard the embedding conforms to, if any (e.g., 'c2pa' for C2PA Section A.7 text manifest embedding)"
          },
          "provider": {
            "type": "string",
            "description": "Organization that performed the embedding (e.g., 'Encypher', 'Digimarc'). Display label and audit context — not a wire identifier."
          },
          "verify_agent": {
            "type": "object",
            "description": "Buyer's representation that this embedding can be verified by a governance agent on the seller's `creative_policy.accepted_verifiers` list. The `agent_url` MUST match (canonicalized) one of the seller's published `accepted_verifiers[].agent_url` entries; sellers reject `sync_creatives` submissions whose `verify_agent.agent_url` is off-list with `PROVENANCE_VERIFIER_NOT_ACCEPTED`. This is buyer-supplied evidence, not buyer-driven routing — the seller is the verifier-of-record and the seller controls which agent it actually calls (the seller MAY use a different on-list agent if it determines this is more appropriate; the seller does not call buyer-asserted endpoints outside its allowlist). MAY be omitted for self-verifiable embeddings (e.g., a C2PA text manifest with a public key the seller already trusts).",
            "properties": {
              "agent_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "description": "URL of the governance agent the buyer represents was used to embed/verify this layer. MUST use the `https://` scheme and MUST appear in the seller's `creative_policy.accepted_verifiers[].agent_url` list (canonicalized per /docs/reference/url-canonicalization: lowercase scheme and host, strip default port, normalize path dot-segments). Sellers MUST NOT call this URL until the canonicalized match is confirmed."
              },
              "feature_id": {
                "type": "string",
                "description": "Optional `feature_id` the buyer represents the seller should request via `get_creative_features` (e.g., `encypher.markers_present_v2`). SHOULD match the `feature_id` declared on the matching `accepted_verifiers[]` entry, or be omitted to defer the selector to the seller. When the seller's entry pins a `feature_id`, that value wins; when neither side pins, the seller selects from the agent's `governance.creative_features` catalog."
              }
            },
            "required": ["agent_url"],
            "additionalProperties": false
          },
          "embedded_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the provenance data was embedded (ISO 8601)"
          }
        },
        "required": ["method", "provider"],
        "additionalProperties": true
      }
    },
    "watermarks": {
      "type": "array",
      "description": "Content watermarks applied to this asset. Each entry declares one watermarking layer: a content modification that encodes an identifier or fingerprint within the asset. Watermarks differ from embedded provenance: a watermark encodes an identifier (who generated it, who owns it), while embedded provenance carries or references a structured provenance record (the full chain of custody). A single asset may carry both. Aligns with C2PA action taxonomy: c2pa.watermarked.bound (watermark linked to a C2PA manifest) and c2pa.watermarked.unbound (watermark independent of any manifest). This is a declaration by the watermarking party. The receiving party (the seller) is the verifier-of-record: it confirms the claim by calling a governance agent it trusts (typically one published in `creative_policy.accepted_verifiers`).",
      "minItems": 1,
      "items": {
        "type": "object",
        "properties": {
          "media_type": {
            "$ref": "/schemas/3.1.0-beta.3/enums/watermark-media-type.json",
            "description": "Media category of the watermarked content"
          },
          "provider": {
            "type": "string",
            "description": "Organization that applied the watermark (e.g., 'Imatag', 'Steg.AI', 'Encypher'). Display label and audit context — not a wire identifier."
          },
          "verify_agent": {
            "type": "object",
            "description": "Buyer's representation that this watermark can be detected by a governance agent on the seller's `creative_policy.accepted_verifiers` list. The `agent_url` MUST match (canonicalized) one of the seller's published `accepted_verifiers[].agent_url` entries; sellers reject `sync_creatives` submissions whose `verify_agent.agent_url` is off-list with `PROVENANCE_VERIFIER_NOT_ACCEPTED`. This is buyer-supplied evidence, not buyer-driven routing — the seller is the verifier-of-record and the seller controls which agent it actually calls (the seller MAY use a different on-list agent if it determines this is more appropriate; the seller does not call buyer-asserted endpoints outside its allowlist).",
            "properties": {
              "agent_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "description": "URL of the governance agent the buyer represents was used to apply/detect this watermark. MUST use the `https://` scheme and MUST appear in the seller's `creative_policy.accepted_verifiers[].agent_url` list (canonicalized per /docs/reference/url-canonicalization: lowercase scheme and host, strip default port, normalize path dot-segments). Sellers MUST NOT call this URL until the canonicalized match is confirmed."
              },
              "feature_id": {
                "type": "string",
                "description": "Optional `feature_id` the buyer represents the seller should request via `get_creative_features` (e.g., `imatag.watermark_detected`). SHOULD match the `feature_id` declared on the matching `accepted_verifiers[]` entry, or be omitted to defer the selector to the seller. When the seller's entry pins a `feature_id`, that value wins; when neither side pins, the seller selects from the agent's `governance.creative_features` catalog."
              }
            },
            "required": ["agent_url"],
            "additionalProperties": false
          },
          "c2pa_action": {
            "$ref": "/schemas/3.1.0-beta.3/enums/c2pa-watermark-action.json",
            "description": "C2PA action classification for this watermark"
          },
          "embedded_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the watermark was applied (ISO 8601)"
          }
        },
        "required": ["media_type", "provider"],
        "additionalProperties": true
      }
    },
    "disclosure": {
      "type": "object",
      "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.",
      "properties": {
        "required": {
          "type": "boolean",
          "description": "The declaring party's claim that AI disclosure is required for this content under applicable regulations. This is a declared signal carried through the supply chain — useful as a routing and audit input — not a regulatory determination made by the protocol. Receiving parties remain responsible for their own jurisdictional analysis and should not treat `required: false` as compliance cover."
        },
        "jurisdictions": {
          "type": "array",
          "description": "Jurisdictions where disclosure obligations apply",
          "items": {
            "type": "object",
            "properties": {
              "country": {
                "type": "string",
                "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')"
              },
              "region": {
                "type": "string",
                "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)"
              },
              "regulation": {
                "type": "string",
                "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')"
              },
              "label_text": {
                "type": "string",
                "description": "Required disclosure label text for this jurisdiction, in the local language"
              },
              "render_guidance": {
                "type": "object",
                "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.",
                "minProperties": 1,
                "properties": {
                  "persistence": {
                    "$ref": "/schemas/3.1.0-beta.3/enums/disclosure-persistence.json",
                    "description": "How long the disclosure must persist during content playback or display"
                  },
                  "min_duration_ms": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial — without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available."
                  },
                  "positions": {
                    "type": "array",
                    "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.",
                    "items": {
                      "$ref": "/schemas/3.1.0-beta.3/enums/disclosure-position.json"
                    },
                    "minItems": 1,
                    "uniqueItems": true
                  },
                  "ext": {
                    "$ref": "/schemas/3.1.0-beta.3/core/ext.json"
                  }
                },
                "additionalProperties": true
              }
            },
            "required": ["country", "regulation"],
            "additionalProperties": true
          },
          "minItems": 1
        }
      },
      "required": ["required"],
      "additionalProperties": true
    },
    "verification": {
      "type": "array",
      "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim — verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.",
      "minItems": 1,
      "items": {
        "type": "object",
        "properties": {
          "verified_by": {
            "type": "string",
            "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')"
          },
          "verified_time": {
            "type": "string",
            "format": "date-time",
            "description": "When the verification was performed (ISO 8601)"
          },
          "result": {
            "type": "string",
            "enum": ["authentic", "ai_generated", "ai_modified", "inconclusive"],
            "description": "Verification outcome"
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Confidence score of the verification result (0.0 to 1.0)"
          },
          "details_url": {
            "type": "string",
            "format": "uri",
            "description": "URL to the full verification report"
          }
        },
        "required": ["verified_by", "result"],
        "additionalProperties": true
      }
    },
    "ext": {
      "$ref": "/schemas/3.1.0-beta.3/core/ext.json"
    }
  },
  "additionalProperties": true
}
