{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://pingcap-datalake.local/schemas/data-product-contract.authored.v0.schema.json",
  "title": "Data Product Authored Contract Schema v0.1.0",
  "description": "JSON Schema for YAML-authored data product contracts. YAML files are parsed to JSON-compatible data before validation.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "id",
    "name",
    "version",
    "owner",
    "domain",
    "purpose",
    "usage",
    "assets",
    "schema",
    "freshness",
    "tests",
    "governance",
    "agent_permissions",
    "compatibility"
  ],
  "properties": {
    "schema_version": {
      "const": "0.1.0",
      "description": "Authored contract schema version. Pre-1.0 schema versions may break."
    },
    "id": {
      "$ref": "#/$defs/identifier",
      "description": "Stable data product identifier, usually <domain>.<product>."
    },
    "name": {
      "$ref": "#/$defs/nonEmptyString"
    },
    "version": {
      "$ref": "#/$defs/semver",
      "description": "Data product contract version."
    },
    "kind": {
      "type": "string",
      "enum": ["product", "source"],
      "default": "product",
      "description": "Contract kind. 'product' is a layered data product (raw/staging/curated/service) owned by the stage that materializes it. 'source' describes an upstream artifact the platform consumes (e.g. exported S3/GCS objects); sources have no layer. The stage that produces the objects owns the source contract; for an externally-managed bucket with no producing stage the source contract is provided instead — inferred and committed under contracts/upstream/, with drift routed to contracts/proposed/ (ADR 0018). Absent means product."
    },
    "layer": {
      "type": "string",
      "enum": ["raw", "staging", "curated", "service"]
    },
    "owner": {
      "$ref": "#/$defs/owner"
    },
    "domain": {
      "$ref": "#/$defs/domain"
    },
    "purpose": {
      "$ref": "#/$defs/nonEmptyString"
    },
    "usage": {
      "$ref": "#/$defs/usage"
    },
    "source": {
      "$ref": "#/$defs/source"
    },
    "assets": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/asset"
      }
    },
    "schema": {
      "$ref": "#/$defs/productSchema"
    },
    "semantics": {
      "$ref": "#/$defs/semantics"
    },
    "freshness": {
      "$ref": "#/$defs/freshness"
    },
    "tests": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/test"
      }
    },
    "declared_lineage": {
      "$ref": "#/$defs/declaredLineage"
    },
    "governance": {
      "$ref": "#/$defs/governance"
    },
    "agent_permissions": {
      "$ref": "#/$defs/agentPermissions"
    },
    "interface": {
      "$ref": "#/$defs/interface"
    },
    "compatibility": {
      "$ref": "#/$defs/compatibility"
    },
    "extensions": {
      "type": "object",
      "description": "Namespaced escape hatch for pre-1.0 experimentation.",
      "additionalProperties": true
    }
  },
  "allOf": [
    {
      "if": {
        "required": ["kind"],
        "properties": { "kind": { "const": "source" } }
      },
      "then": {
        "required": ["source"],
        "properties": { "layer": false }
      },
      "else": {
        "required": ["layer"]
      }
    },
    {
      "if": {
        "properties": {
          "layer": { "const": "raw" }
        },
        "required": ["layer"]
      },
      "then": {
        "required": ["source"],
        "properties": {
          "governance": {
            "required": ["access", "retention"]
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "layer": { "const": "staging" }
        },
        "required": ["layer"]
      },
      "then": {
        "required": ["source"],
        "properties": {
          "tests": {
            "minItems": 1
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "layer": { "const": "curated" }
        },
        "required": ["layer"]
      },
      "then": {
        "required": ["semantics"],
        "properties": {
          "tests": {
            "minItems": 1
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "layer": { "const": "service" }
        },
        "required": ["layer"]
      },
      "then": {
        "required": ["semantics", "interface"],
        "properties": {
          "tests": {
            "minItems": 1
          },
          "interface": {
            "required": ["kind", "entrypoints"]
          }
        }
      }
    }
  ],
  "$defs": {
    "identifier": {
      "type": "string",
      "pattern": "^[a-z_][a-z0-9_.-]*$"
    },
    "nonEmptyString": {
      "type": "string",
      "minLength": 1
    },
    "semver": {
      "type": "string",
      "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
    },
    "classification": {
      "type": "string",
      "pattern": "^(public|internal|confidential|restricted|pii|financial|customer_data|operational_sensitive|x_[a-z][a-z0-9_]*)(\\.[a-z][a-z0-9_]*)*$"
    },
    "duration": {
      "type": "string",
      "description": "ISO 8601 duration, for example PT24H, P7D, or P90D."
    },
    "contact": {
      "type": "object",
      "additionalProperties": false,
      "required": ["kind", "value"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["email", "slack", "github", "url", "other"]
        },
        "value": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "owner": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "name"],
      "properties": {
        "type": {
          "type": "string",
          "enum": ["team", "user", "service"]
        },
        "name": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "contacts": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/contact"
          }
        },
        "approvers": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        }
      }
    },
    "domain": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name"],
      "properties": {
        "name": {
          "$ref": "#/$defs/identifier"
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "usage": {
      "type": "object",
      "additionalProperties": false,
      "required": ["intended", "prohibited"],
      "properties": {
        "intended": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        },
        "prohibited": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        }
      }
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "required": ["kind", "system"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["database", "api", "file", "stream", "application", "manual", "other"]
        },
        "system": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "identifiers": {
          "type": "object",
          "additionalProperties": {
            "type": ["string", "number", "boolean"]
          }
        }
      }
    },
    "asset": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "kind", "ref"],
      "properties": {
        "id": {
          "$ref": "#/$defs/identifier"
        },
        "kind": {
          "type": "string",
          "enum": ["table", "view", "model", "file", "api", "notebook", "other"]
        },
        "ref": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "materialization": {
          "type": "string",
          "enum": ["table", "view", "incremental", "external", "ephemeral", "api", "other"]
        },
        "produced_by": {
          "type": "object",
          "additionalProperties": false,
          "required": ["kind", "ref"],
          "properties": {
            "kind": {
              "type": "string",
              "enum": ["dbt", "dagster", "dlt", "sql", "python", "manual", "other"]
            },
            "ref": {
              "$ref": "#/$defs/nonEmptyString"
            }
          }
        },
        "schema_ref": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "productSchema": {
      "type": "object",
      "additionalProperties": false,
      "required": ["kind"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["relational", "document", "file", "api", "mixed"]
        },
        "schema_ref": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "columns": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/column"
          }
        }
      },
      "anyOf": [
        { "required": ["schema_ref"] },
        { "required": ["columns"] }
      ]
    },
    "column": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "type"],
      "properties": {
        "name": {
          "$ref": "#/$defs/identifier"
        },
        "type": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "nullable": {
          "type": "boolean"
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "semantic_type": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "classifications": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/classification"
          }
        }
      }
    },
    "semantics": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "terms": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/semanticTerm"
          }
        },
        "entities": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/semanticTerm"
          }
        },
        "dimensions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/semanticTerm"
          }
        },
        "metrics": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/metric"
          }
        }
      }
    },
    "semanticTerm": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "description"],
      "properties": {
        "name": {
          "$ref": "#/$defs/identifier"
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "metric": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "expression", "description"],
      "properties": {
        "name": {
          "$ref": "#/$defs/identifier"
        },
        "expression": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "grain": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "freshness": {
      "type": "object",
      "additionalProperties": false,
      "required": ["max_age"],
      "properties": {
        "max_age": {
          "$ref": "#/$defs/duration"
        },
        "timezone": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "schedule_ref": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "degrade_after": {
          "$ref": "#/$defs/duration"
        }
      }
    },
    "test": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "type", "severity", "description"],
      "properties": {
        "id": {
          "$ref": "#/$defs/identifier"
        },
        "type": {
          "type": "string",
          "enum": ["sql", "dbt", "expectation", "custom"]
        },
        "severity": {
          "type": "string",
          "enum": ["blocking", "degrading", "informational", "experimental"]
        },
        "description": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "applies_to": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/identifier"
          }
        },
        "sql": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "dbt": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "selector": {
              "$ref": "#/$defs/nonEmptyString"
            },
            "test_name": {
              "$ref": "#/$defs/nonEmptyString"
            }
          }
        },
        "expectation": {
          "type": "object",
          "additionalProperties": true
        },
        "command": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "declaredLineage": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "upstreams": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/lineageRef"
          }
        },
        "downstreams": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/lineageRef"
          }
        }
      }
    },
    "lineageRef": {
      "type": "object",
      "additionalProperties": false,
      "required": ["kind", "ref"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["data_product", "source", "table", "view", "file", "job", "api", "other"]
        },
        "ref": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "contract_version": {
          "$ref": "#/$defs/semver"
        },
        "required": {
          "type": "boolean"
        }
      }
    },
    "governance": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "classifications": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/classification"
          }
        },
        "classification_exceptions": {
          "type": "array",
          "description": "Approved exceptions that weaken or refine inherited classifications.",
          "items": {
            "$ref": "#/$defs/classificationException"
          }
        },
        "access": {
          "$ref": "#/$defs/access"
        },
        "masking": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/maskingRule"
          }
        },
        "retention": {
          "$ref": "#/$defs/retention"
        },
        "audit": {
          "$ref": "#/$defs/audit"
        },
        "policy_refs": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        }
      }
    },
    "classificationException": {
      "type": "object",
      "additionalProperties": false,
      "required": ["classification", "reason", "approved_by"],
      "properties": {
        "classification": {
          "$ref": "#/$defs/classification"
        },
        "reason": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "approved_by": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "expires_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "access": {
      "type": "object",
      "additionalProperties": false,
      "required": ["default"],
      "properties": {
        "default": {
          "type": "string",
          "enum": ["public", "internal", "restricted", "deny"]
        },
        "allowed_roles": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/identifier"
          }
        },
        "denied_roles": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/identifier"
          }
        },
        "request_policy": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "maskingRule": {
      "type": "object",
      "additionalProperties": false,
      "required": ["field", "policy"],
      "properties": {
        "field": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "policy": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "retention": {
      "type": "object",
      "additionalProperties": false,
      "required": ["period"],
      "properties": {
        "period": {
          "$ref": "#/$defs/duration"
        },
        "deletion_policy": {
          "$ref": "#/$defs/nonEmptyString"
        }
      }
    },
    "audit": {
      "type": "object",
      "additionalProperties": false,
      "required": ["required"],
      "properties": {
        "required": {
          "type": "boolean"
        },
        "events": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["query", "export", "policy_change", "contract_change", "agent_action", "other"]
          }
        }
      }
    },
    "agentPermissions": {
      "type": "object",
      "additionalProperties": false,
      "required": ["default"],
      "properties": {
        "default": {
          "type": "string",
          "enum": ["deny", "observe"]
        },
        "grants": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/agentGrant"
          }
        }
      }
    },
    "agentGrant": {
      "type": "object",
      "additionalProperties": false,
      "required": ["principal", "max_risk_tier", "allowed_actions"],
      "properties": {
        "principal": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "max_risk_tier": {
          "type": "string",
          "enum": ["observe", "reversible_workspace", "controlled_operational", "approval_gated"]
        },
        "allowed_actions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/identifier"
          }
        },
        "constraints": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        },
        "approval_required_for": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/identifier"
          }
        }
      }
    },
    "interface": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["mart", "semantic_metric", "bi_view", "api", "agent_tool", "reverse_etl", "notebook", "other"]
        },
        "entrypoints": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        },
        "consumers": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/nonEmptyString"
          }
        }
      }
    },
    "compatibility": {
      "type": "object",
      "additionalProperties": false,
      "required": ["change_policy"],
      "properties": {
        "change_policy": {
          "type": "string",
          "enum": ["semver"]
        },
        "deprecation_window": {
          "$ref": "#/$defs/duration"
        },
        "migration_notes": {
          "$ref": "#/$defs/nonEmptyString"
        },
        "compatible_with": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/semver"
          }
        }
      }
    }
  }
}
