{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://ucan.xyz/schemas/policy.json",
  "title": "UCAN Policy Language",
  "description": "Policy statements and selectors for constraining invocation arguments",
  "$defs": {
    "Selector": {
      "title": "Policy Selector",
      "description": "jq-inspired selector for navigating IPLD data structures",
      "type": "string",
      "pattern": "^\\.(([a-zA-Z_][a-zA-Z0-9_]*)|(\\[[^\\]]+\\])|(\\[\\])|(\\[-?\\d+\\])|(\\[\\d*:\\d*\\]))?((\\.[a-zA-Z_][a-zA-Z0-9_]*)|(\\[[^\\]]+\\])|(\\[\\])|(\\[-?\\d+\\])|(\\[\\d*:\\d*\\]))*\\??$",
      "examples": [
        ".",
        ".foo",
        ".bar[0]",
        ".items[-1]",
        ".data[2:5]",
        ".optional?"
      ]
    },
    "GlobPattern": {
      "title": "Glob Pattern",
      "description": "Pattern for 'like' operator. * = wildcard, \\* = literal",
      "type": "string",
      "examples": [
        "*@example.com",
        "prefix*suffix"
      ]
    },
    "EqualityOperator": {
      "title": "Equality Operator",
      "type": "string",
      "enum": [
        "==",
        "!="
      ]
    },
    "InequalityOperator": {
      "title": "Inequality Operator",
      "type": "string",
      "enum": [
        ">",
        ">=",
        "<",
        "<="
      ]
    },
    "EqualityStatement": {
      "title": "Equality Statement",
      "description": "Deep comparison: [operator, selector, value]",
      "type": "array",
      "prefixItems": [
        {
          "$ref": "#/$defs/EqualityOperator"
        },
        {
          "$ref": "#/$defs/Selector"
        },
        {}
      ],
      "minItems": 3,
      "maxItems": 3,
      "examples": [
        [
          "==",
          ".status",
          "draft"
        ],
        [
          "!=",
          ".deleted",
          true
        ]
      ]
    },
    "InequalityStatement": {
      "title": "Inequality Statement",
      "description": "Numeric comparison: [operator, selector, number]",
      "type": "array",
      "prefixItems": [
        {
          "$ref": "#/$defs/InequalityOperator"
        },
        {
          "$ref": "#/$defs/Selector"
        },
        {
          "type": "number"
        }
      ],
      "minItems": 3,
      "maxItems": 3,
      "examples": [
        [
          ">",
          ".age",
          18
        ],
        [
          "<=",
          ".price",
          100.50
        ]
      ]
    },
    "LikeStatement": {
      "title": "Like Statement",
      "description": "Glob pattern matching: ['like', selector, pattern]",
      "type": "array",
      "prefixItems": [
        {
          "const": "like"
        },
        {
          "$ref": "#/$defs/Selector"
        },
        {
          "$ref": "#/$defs/GlobPattern"
        }
      ],
      "minItems": 3,
      "maxItems": 3,
      "examples": [
        [
          "like",
          ".email",
          "*@example.com"
        ]
      ]
    },
    "NotStatement": {
      "title": "Not Statement",
      "description": "Logical negation: ['not', statement]",
      "type": "array",
      "prefixItems": [
        {
          "const": "not"
        },
        {
          "$ref": "#/$defs/PolicyStatement"
        }
      ],
      "minItems": 2,
      "maxItems": 2
    },
    "AndStatement": {
      "title": "And Statement",
      "description": "Logical AND: ['and', [statements...]]. Empty array = true",
      "type": "array",
      "prefixItems": [
        {
          "const": "and"
        },
        {
          "type": "array",
          "items": {
            "$ref": "#/$defs/PolicyStatement"
          }
        }
      ],
      "minItems": 2,
      "maxItems": 2
    },
    "OrStatement": {
      "title": "Or Statement",
      "description": "Logical OR: ['or', [statements...]]. Empty array = true",
      "type": "array",
      "prefixItems": [
        {
          "const": "or"
        },
        {
          "type": "array",
          "items": {
            "$ref": "#/$defs/PolicyStatement"
          }
        }
      ],
      "minItems": 2,
      "maxItems": 2
    },
    "AllStatement": {
      "title": "All Statement",
      "description": "Universal quantifier: ['all', selector, statement]",
      "type": "array",
      "prefixItems": [
        {
          "const": "all"
        },
        {
          "$ref": "#/$defs/Selector"
        },
        {
          "$ref": "#/$defs/PolicyStatement"
        }
      ],
      "minItems": 3,
      "maxItems": 3,
      "examples": [
        [
          "all",
          ".reviewers",
          [
            "like",
            ".email",
            "*@example.com"
          ]
        ]
      ]
    },
    "AnyStatement": {
      "title": "Any Statement",
      "description": "Existential quantifier: ['any', selector, statement]",
      "type": "array",
      "prefixItems": [
        {
          "const": "any"
        },
        {
          "$ref": "#/$defs/Selector"
        },
        {
          "$ref": "#/$defs/PolicyStatement"
        }
      ],
      "minItems": 3,
      "maxItems": 3,
      "examples": [
        [
          "any",
          ".tags",
          [
            "==",
            ".",
            "urgent"
          ]
        ]
      ]
    },
    "PolicyStatement": {
      "title": "Policy Statement",
      "description": "A single policy predicate expression",
      "oneOf": [
        {
          "$ref": "#/$defs/EqualityStatement"
        },
        {
          "$ref": "#/$defs/InequalityStatement"
        },
        {
          "$ref": "#/$defs/LikeStatement"
        },
        {
          "$ref": "#/$defs/NotStatement"
        },
        {
          "$ref": "#/$defs/AndStatement"
        },
        {
          "$ref": "#/$defs/OrStatement"
        },
        {
          "$ref": "#/$defs/AllStatement"
        },
        {
          "$ref": "#/$defs/AnyStatement"
        }
      ]
    },
    "Policy": {
      "title": "UCAN Policy",
      "description": "Array of statements forming implicit AND. Constrains invocation args.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/PolicyStatement"
      },
      "examples": [
        [],
        [
          [
            "==",
            ".from",
            "alice@example.com"
          ]
        ],
        [
          [
            "==",
            ".status",
            "draft"
          ],
          [
            "all",
            ".reviewer",
            [
              "like",
              ".email",
              "*@example.com"
            ]
          ]
        ]
      ]
    }
  }
}
