{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/welkaim/ea-codex/schemas/v1/data-contract.json",
  "title": "DataContract",
  "description": "Consumer-facing data contract between a data product and one or more consumers. A DataContract operationalizes a single channel of access governed by a DataProductContract: it carries the technical schema, the freshness and availability SLA, the quality enforcement, the versioning and deprecation policy, and the access pattern. A single DataProductContract typically governs multiple DataContract artifacts, one per consumption pattern (governed API, federated query, event stream, clean-room view). Where the DataProductContract answers 'is this data product allowed to exist, and under what conditions', the DataContract answers 'if I subscribe to this data product through this interface, what do I get and what am I allowed to do with it'.",
  "type": "object",
  "required": ["apiVersion", "kind", "metadata", "spec"],
  "properties": {
    "apiVersion": { "$ref": "_common.json#/$defs/apiVersion" },
    "kind": { "type": "string", "const": "DataContract" },
    "metadata": { "$ref": "_common.json#/$defs/metadata" },
    "spec": {
      "type": "object",
      "required": ["dataProductRef", "accessPattern", "schema", "sla", "versioning"],
      "properties": {
        "dataProductRef": {
          "type": "string",
          "description": "Identifier of the DataProductContract this contract operationalizes."
        },
        "businessObjectRef": {
          "type": "string",
          "description": "Identifier of the BusinessObject the contract carries. Optional when the data product realizes a single object; required when the contract scopes a specific object out of a multi-object product."
        },
        "consumers": {
          "type": "array",
          "description": "Named consumers of this contract. Each consumer must declare a purpose that matches one of the purposes in the parent DataProductContract.",
          "items": {
            "type": "object",
            "required": ["name", "declaredPurpose"],
            "properties": {
              "name": { "type": "string" },
              "declaredPurpose": { "type": "string" },
              "consumerType": {
                "type": "string",
                "enum": ["agent", "application", "analytics", "downstream-product", "external-partner"]
              }
            },
            "additionalProperties": true
          }
        },
        "accessPattern": {
          "type": "object",
          "required": ["pattern"],
          "description": "How consumers reach the data. Mirrors the DataProductContract.spec.interfaces[].pattern enumeration but binds it to a specific endpoint and schema for this contract.",
          "properties": {
            "pattern": {
              "type": "string",
              "enum": ["governed-api", "federated-query", "semantic-retrieval", "clean-room-analysis", "event-stream"]
            },
            "endpoint": { "type": "string" },
            "protocol": {
              "type": "string",
              "description": "Wire protocol (e.g., 'https', 'grpc', 'jdbc', 'kafka', 'mcp')."
            }
          },
          "additionalProperties": true
        },
        "schema": {
          "type": "object",
          "required": ["fields"],
          "description": "Technical schema for the contract. Distinct from the BusinessObject's logical attributes: this is the wire-format schema consumers will receive.",
          "properties": {
            "schemaRef": {
              "type": "string",
              "description": "External schema artifact (JSON Schema, Avro, Protobuf, OpenAPI) that the contract conforms to. Optional but recommended for production contracts."
            },
            "format": {
              "type": "string",
              "enum": ["json", "avro", "protobuf", "parquet", "iceberg", "openapi"]
            },
            "fields": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": ["name", "type"],
                "properties": {
                  "name": { "type": "string" },
                  "type": {
                    "type": "string",
                    "description": "Wire-format type (e.g., 'string', 'int64', 'timestamp', 'array<string>', 'object')."
                  },
                  "nullable": { "type": "boolean" },
                  "description": { "type": "string" },
                  "businessObjectAttribute": {
                    "type": "string",
                    "description": "If this wire field maps to an attribute on the parent BusinessObject, name the attribute here. Enables traceability from wire schema back to canonical definition."
                  },
                  "sensitivity": {
                    "type": "string",
                    "enum": ["public", "internal", "confidential", "restricted", "pii", "phi"]
                  },
                  "redactionRule": {
                    "type": "string",
                    "description": "How sensitive fields are transformed for this contract (e.g., 'hash', 'tokenize', 'truncate', 'remove-for-non-eu-consumers')."
                  }
                },
                "additionalProperties": true
              }
            }
          },
          "additionalProperties": true
        },
        "sla": {
          "type": "object",
          "required": ["freshness", "availability"],
          "description": "Service-level agreement enforced by the contract. Distinct from DataProductContract.qualityAttributes (which states targets at the product level): the SLA here is contracted with consumers and must be observable.",
          "properties": {
            "freshness": {
              "type": "string",
              "description": "Maximum staleness from source (e.g., '5min', '1h', '24h', 'real-time')."
            },
            "availability": {
              "type": "string",
              "description": "Availability target (e.g., '99.9%', '99.95% during business hours')."
            },
            "latencyP99": {
              "type": "string",
              "description": "Read-path P99 latency target (e.g., '200ms', '5s', 'best-effort')."
            },
            "throughput": {
              "type": "string",
              "description": "Sustained throughput target (e.g., '1000 req/s', '10k events/min')."
            }
          },
          "additionalProperties": true
        },
        "qualityEnforcement": {
          "type": "array",
          "description": "Quality checks that gate publication of every record or batch. Distinct from quality attribute targets stated in the parent contract: these are enforced, not aspirational.",
          "items": {
            "type": "object",
            "required": ["check", "action"],
            "properties": {
              "check": {
                "type": "string",
                "description": "What is checked (e.g., 'completeness', 'referential-integrity', 'schema-validation', 'business-object-semantic-rules')."
              },
              "threshold": { "type": "string" },
              "action": {
                "type": "string",
                "enum": ["block", "quarantine", "warn", "annotate"]
              },
              "enforcedBy": {
                "type": "string",
                "description": "Reference to a RegoPackage, data-quality engine, or pipeline check that runs the rule."
              }
            },
            "additionalProperties": true
          }
        },
        "versioning": {
          "type": "object",
          "required": ["currentVersion", "compatibilityPolicy"],
          "description": "How contract versions evolve and what consumers can rely on.",
          "properties": {
            "currentVersion": {
              "type": "string",
              "description": "Current contract version, distinct from metadata.version (which versions the artifact itself)."
            },
            "compatibilityPolicy": {
              "type": "string",
              "enum": ["backward-compatible-only", "forward-compatible-only", "full-compatibility", "breaking-allowed-with-notice"]
            },
            "deprecationNoticePeriod": {
              "type": "string",
              "description": "Minimum notice period before a deprecated contract is removed (e.g., '90d', '180d')."
            },
            "supportedVersions": {
              "type": "array",
              "description": "Versions still served. Older versions are typically deprecated, then retired.",
              "items": { "type": "string" }
            }
          },
          "additionalProperties": true
        },
        "evidence": {
          "type": "object",
          "description": "Operational evidence the contract emits. Required for regulated contracts; optional for internal ones.",
          "properties": {
            "accessLog": { "type": "string" },
            "qualityReport": { "type": "string" },
            "lineage": { "type": "string" }
          },
          "additionalProperties": true
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": false
}
