{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://acdl.cloudinit.dev/schemas/contract.schema.json",
  "title": "ACDL Consumer Contract",
  "description": "A consumer contract declares intent: which infrastructure to deploy, in which environment, with which inputs. The contract is keyed by an operational id (3-6 char acronym, becomes the stack name for state keys, tags, and outbox events) and a human-readable name (becomes the stack title for display and evidence). The infrastructure map is keyed by module name; each entry carries an optional version (defaults to the latest published version from the module registry) and per-module inputs. The contract resolver resolves each infrastructure entry against modules/registry.json, then merges them into a single Target Stack instance.",
  "type": "object",
  "required": ["id", "name", "environment", "infrastructure"],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-]{2,5}$",
      "description": "Short operational acronym (3-6 chars, lowercase + digits + hyphens). Becomes stack.name: the Terraform state key (spike/<id>/terraform.tfstate), the ECS service name, the outbox event identity, and the resource naming prefix. Stable across deploys."
    },
    "name": {
      "type": "string",
      "minLength": 3,
      "description": "Full human-readable stack name. Becomes stack.title: the display name in PR comments, evidence records, and leadership dashboards."
    },
    "environment": {
      "type": "string",
      "enum": ["dev", "qa", "prod", "dr"],
      "description": "Target environment. Applies to every module in the contract — a contract deploys all its infrastructure into one environment. dev = autonomous; qa/prod/dr = HITL gates."
    },
    "infrastructure": {
      "type": "object",
      "minProperties": 1,
      "description": "Map of modules to deploy, keyed by module name (matching a registry key in modules/registry.json). Each value carries an optional version (defaults to the latest published version) and per-module inputs. One entry = single-module deploy; N entries = multi-module manifest deployed in one pipeline run.",
      "patternProperties": {
        "^[a-z][a-z0-9-]*$": {
          "type": "object",
          "required": ["inputs"],
          "properties": {
            "version": {
              "type": "string",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "description": "Module version pin (semver). Omit to default to the latest non-deprecated version from modules/registry.json."
            },
            "inputs": {
              "type": "object",
              "description": "Module-specific inputs (bucket_name, region, image, port, cpu, memory, desired_count, env, etc.). Validated at resolution time against the module's interface.json or composition.json. May include deletion_protection (boolean, default true — set to false only during decommission) and uptime_enabled (boolean, default true — set to false to disable uptime monitoring).",
              "additionalProperties": {"type": ["string", "number", "boolean", "object", "array"]}
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}