{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:swarm-v2:pod-policy",
  "title": "Approved execution Pod policy",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "template_version", "namespace", "service_account", "runtime_class_name", "image_repository", "termination_grace_seconds", "provider_accounts", "profiles", "probes"],
  "properties": {
    "schema_version": {"const": 1},
    "template_version": {"$ref": "#/$defs/label_value"},
    "namespace": {"$ref": "#/$defs/dns_label"},
    "service_account": {"$ref": "#/$defs/dns_label"},
    "runtime_class_name": {"$ref": "#/$defs/dns_label"},
    "image_repository": {"type": "string", "maxLength": 200, "pattern": "^[a-z0-9]([a-z0-9.-]*[a-z0-9])?(:[0-9]{1,5})?(/[a-z0-9]+([._-][a-z0-9]+)*)+$"},
    "brain_url": {"type": "string", "maxLength": 200, "pattern": "^https?://[A-Za-z0-9.-]+(:[0-9]{1,5})?(/[A-Za-z0-9._~/-]*)?$"},
    "git_app_secret_name": {"$ref": "#/$defs/dns_label"},
    "redis_secret_name": {"allOf": [{"$ref": "#/$defs/dns_label"}, {"pattern": "-worker$"}], "description": "The worker role Redis Secret; the agent container reads only its url key as AGENTIHOOKS_SWARM_REDIS_URL, never the administrator credential."},
    "termination_grace_seconds": {"type": "integer", "minimum": 1, "maximum": 900},
    "mounts": {"type": "array", "maxItems": 8, "items": {"$ref": "#/$defs/mount"}, "description": "Shared storage. A seed and the node cache mount read only; an artifact mount is writable only in the subPath of its execution. The rendered Pod passes the storage checker or is refused."},
    "bundle": {
      "type": "object",
      "additionalProperties": false,
      "required": ["image_repository", "tag", "pull_access"],
      "properties": {
        "image_repository": {"type": "string", "maxLength": 200, "pattern": "^[a-z0-9]([a-z0-9.-]*[a-z0-9])?(:[0-9]{1,5})?(/[a-z0-9]+([._-][a-z0-9]+)*)+$"},
        "tag": {"type": "string", "pattern": "^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$"},
        "pull_access": {"allOf": [{"$ref": "#/$defs/dns_label"}, {"not": {"pattern": "^swarm-account-"}}], "description": "The image pull Secret only the kubelet reads; never a provider account Secret."}
      },
      "description": "The private bundle image. An init container copies its /bundle, /linked and /revision.json into a Pod private folder the agent mounts read only."
    },
    "provider_accounts": {"type": "array", "maxItems": 64, "uniqueItems": true, "items": {"$ref": "#/$defs/account"}},
    "worker_pool": {
      "type": "object",
      "additionalProperties": false,
      "required": ["pods", "cpu_millis", "memory_mib"],
      "properties": {
        "pods": {"type": "integer", "minimum": 1, "maximum": 1000},
        "cpu_millis": {"type": "integer", "minimum": 1, "maximum": 10000000},
        "memory_mib": {"type": "integer", "minimum": 1, "maximum": 67108864}
      }
    },
    "profiles": {
      "type": "object",
      "minProperties": 1,
      "maxProperties": 16,
      "propertyNames": {"$ref": "#/$defs/dns_label"},
      "additionalProperties": {"$ref": "#/$defs/profile"}
    },
    "probes": {
      "type": "object",
      "additionalProperties": false,
      "required": ["herdr_timeout_seconds", "brain_timeout_seconds", "startup", "readiness", "liveness"],
      "properties": {
        "herdr_timeout_seconds": {"type": "number", "exclusiveMinimum": 0, "maximum": 30},
        "brain_timeout_seconds": {"type": "number", "exclusiveMinimum": 0, "maximum": 30},
        "startup": {"$ref": "#/$defs/probe"},
        "readiness": {"$ref": "#/$defs/probe"},
        "liveness": {"$ref": "#/$defs/probe"}
      }
    }
  },
  "$defs": {
    "dns_label": {"type": "string", "pattern": "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"},
    "account": {"type": "string", "maxLength": 62, "pattern": "^[A-Za-z0-9]([A-Za-z0-9._+-]*[A-Za-z0-9])?@[A-Za-z0-9]([A-Za-z0-9.-]*[A-Za-z0-9])?$", "description": "An admitted provider account email, matched case blind. Pods carry its lower cased key (the at sign as at, every other symbol a dash) as the swarm.agentihooks.io/provider-account label and read only that key of Secret swarm-claude-creds as AH_CC_TOKEN_ plus the key with underscores; 62 characters keep the key within a 63 character label."},
    "label_value": {"type": "string", "pattern": "^[A-Za-z0-9]([A-Za-z0-9._-]{0,61}[A-Za-z0-9])?$"},
    "label_key": {"type": "string", "pattern": "^([a-z0-9]([a-z0-9.-]{0,251}[a-z0-9])?/)?[A-Za-z0-9]([A-Za-z0-9._-]{0,61}[A-Za-z0-9])?$"},
    "quantity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["memory_mib", "cpu_millis", "ephemeral_mib"],
      "properties": {
        "memory_mib": {"type": "integer", "minimum": 64, "maximum": 262144},
        "cpu_millis": {"type": "integer", "minimum": 100, "maximum": 64000},
        "ephemeral_mib": {"type": "integer", "minimum": 2048, "maximum": 204800}
      }
    },
    "toleration": {
      "type": "object",
      "additionalProperties": false,
      "required": ["key", "operator", "effect"],
      "properties": {
        "key": {"$ref": "#/$defs/label_key"},
        "operator": {"enum": ["Equal", "Exists"]},
        "value": {"$ref": "#/$defs/label_value"},
        "effect": {"enum": ["NoSchedule", "PreferNoSchedule", "NoExecute"]}
      },
      "if": {"properties": {"operator": {"const": "Exists"}}},
      "then": {"not": {"required": ["value"]}}
    },
    "profile": {
      "type": "object",
      "additionalProperties": false,
      "required": ["limits", "node_selector", "tolerations", "excluded_nodes"],
      "properties": {
        "limits": {"$ref": "#/$defs/quantity"},
        "requests": {
          "type": "object",
          "additionalProperties": false,
          "required": ["cpu_millis"],
          "description": "A CPU request below the CPU limit lets a worker burst; memory has no request here, so a worker always requests its whole memory limit and never overcommits node memory.",
          "properties": {"cpu_millis": {"type": "integer", "minimum": 100, "maximum": 64000}}
        },
        "node_selector": {
          "type": "object",
          "maxProperties": 8,
          "propertyNames": {"$ref": "#/$defs/label_key"},
          "additionalProperties": {"$ref": "#/$defs/label_value"}
        },
        "tolerations": {"type": "array", "maxItems": 8, "items": {"$ref": "#/$defs/toleration"}},
        "excluded_nodes": {
          "type": "object",
          "maxProperties": 8,
          "propertyNames": {"$ref": "#/$defs/label_key"},
          "additionalProperties": {"type": "array", "minItems": 1, "maxItems": 8, "items": {"$ref": "#/$defs/label_value"}}
        }
      }
    },
    "absolute_path": {"type": "string", "maxLength": 200, "pattern": "^/[A-Za-z0-9._/-]*$"},
    "mount": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "purpose", "mount_path", "source"],
      "properties": {
        "name": {"$ref": "#/$defs/dns_label", "maxLength": 40},
        "purpose": {"enum": ["seed", "artifact", "cache"]},
        "mount_path": {"$ref": "#/$defs/absolute_path"},
        "source": {
          "oneOf": [
            {"type": "object", "additionalProperties": false, "required": ["claim"], "properties": {"claim": {"$ref": "#/$defs/dns_label"}}},
            {"type": "object", "additionalProperties": false, "required": ["host_path"], "properties": {"host_path": {"$ref": "#/$defs/absolute_path"}}},
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["nfs"],
              "properties": {
                "nfs": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": ["server", "path"],
                  "properties": {"server": {"type": "string", "maxLength": 200, "pattern": "^[A-Za-z0-9.-]+$"}, "path": {"$ref": "#/$defs/absolute_path"}}
                }
              }
            }
          ]
        }
      }
    },
    "probe": {
      "type": "object",
      "additionalProperties": false,
      "required": ["initial_delay_seconds", "period_seconds", "timeout_seconds", "failure_threshold"],
      "properties": {
        "initial_delay_seconds": {"type": "integer", "minimum": 0, "maximum": 300},
        "period_seconds": {"type": "integer", "minimum": 1, "maximum": 300},
        "timeout_seconds": {"type": "integer", "minimum": 1, "maximum": 120},
        "failure_threshold": {"type": "integer", "minimum": 1, "maximum": 120}
      }
    }
  }
}
