{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "JSON-RPC Flow Schema",
  "description": "A schema for defining JSON-RPC workflows as a series of composable, nestable operations. Each flow consists of a sequence of steps that can be executed based on their data dependencies and control flow structures.",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "A unique identifier for the flow. Should be descriptive and follow kebab-case naming convention."
    },
    "description": {
      "type": "string",
      "description": "A detailed description of what the flow does, its purpose, and expected outcomes."
    },
    "policies": {
      "type": "object",
      "description": "Policies for the flow. The global policy applies to the workflow as whole. The step policy applies to the steps who do not have their own policy.",
      "properties": {
        "global": {
          "$ref": "#/definitions/Policies"
        },
        "step": {
          "$ref": "#/definitions/Policies"
        }
      }
    },
    "context": {
      "type": "object",
      "description": "Optional global context variables available throughout the flow execution.",
      "additionalProperties": true
    },
    "steps": {
      "type": "array",
      "description": "An ordered sequence of steps to execute. While the order provides a visual guide, actual execution order is determined by data dependencies between steps.",
      "items": {
        "$ref": "#/definitions/Step"
      },
      "minItems": 1
    }
  },
  "definitions": {
    "Step": {
      "type": "object",
      "description": "A single step in the flow. Each step must have exactly one of the primitive operations: request, transform, loop, or condition.",
      "required": ["name"],
      "properties": {
        "name": {
          "type": "string",
          "description": "A unique identifier for the step within the flow. Used for referencing step results in expressions.",
          "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
        },
        "policies": {
          "$ref": "#/definitions/Policies"
        }
      },
      "oneOf": [
        { "$ref": "#/definitions/RequestStep" },
        { "$ref": "#/definitions/TransformStep" },
        { "$ref": "#/definitions/LoopStep" },
        { "$ref": "#/definitions/ConditionStep" },
        { "$ref": "#/definitions/StopStep" }
      ]
    },
    "Policies": {
      "type": "object",
      "description": "Optional policies for the step. If not provided, the default policies will be used.",
      "properties": {
        "retryPolicy": {
          "type": "object",
          "description": "Optional retry policy. If not provided, the default retry policy will be used.",
          "properties": {
            "maxAttempts": {
              "type": "number",
              "description": "The maximum number of attempts to retry the step. if the step type has a more specific maxAttempts, the default will be overridden, however, if set, it will override both the default and the step type specific maxAttempts. 0 means unlimited attempts (until timeout)",
              "default": 3,
              "minimum": 0,
              "maximum": 100
            },
            "backoff": {
              "type": "object",
              "description": "The backoff policy for the step. If not provided, the default backoff policy will be used.",
              "properties": {
                "strategy": {
                  "type": "string",
                  "description": "The strategy to use for the backoff. If not provided, the default backoff strategy will be used.",
                  "default": "exponential",
                  "enum": ["exponential", "linear"]
                },
                "initial": {
                  "type": "number",
                  "description": "The initial delay in milliseconds."
                },
                "multiplier": {
                  "type": "number",
                  "description": "The multiplier/exponent for the backoff."
                },
                "maxDelay": {
                  "type": "number",
                  "description": "The maximum delay in milliseconds.",
                  "default": 5000,
                  "minimum": 0,
                  "maximum": 3600000
                }
              }
            },
            "retryableErrors": {
              "type": "array",
              "description": "An array of error codes that are retryable.",
              "items": {
                "type": "string",
                "enum": [
                  "VALIDATION_ERROR",
                  "INVALID_INPUT",
                  "SCHEMA_VALIDATION",
                  "TYPE_ERROR",
                  "EXECUTION_ERROR",
                  "RUNTIME_ERROR",
                  "NETWORK_ERROR",
                  "RESOURCE_ERROR",
                  "MAX_RETRIES_EXCEEDED",
                  "TIMEOUT_ERROR",
                  "OPERATION_TIMEOUT",
                  "DEADLINE_EXCEEDED",
                  "STATE_ERROR",
                  "INVALID_STATE",
                  "MISSING_DEPENDENCY",
                  "INTERNAL_ERROR",
                  "CONFIG_ERROR"
                ]
              }
            }
          }
        },
        "timeout": {
          "type": "object",
          "description": "Timeout policy. If not provided, the default timeout policy will be used.",
          "properties": {
            "timeout": {
              "type": "number",
              "description": "Optional timeout for the step in milliseconds. If not provided, the default timeout will be used.",
              "default": 10000,
              "minimum": 0,
              "maximum": 3600000
            },
            "expressionEval": {
              "type": "number",
              "description": "Optional timeout for expression evaluation in milliseconds. If not provided, the default expression timeout will be used.",
              "default": 1000,
              "minimum": 0,
              "maximum": 3600000
            }
          }
        }
      }
    },
    "RequestStep": {
      "type": "object",
      "description": "A step that makes a JSON-RPC request. This is the primary mechanism for external interactions.",
      "required": ["name", "request"],
      "properties": {
        "request": {
          "type": "object",
          "required": ["method", "params"],
          "properties": {
            "method": {
              "type": "string",
              "description": "The JSON-RPC method to call."
            },
            "params": {
              "type": "object",
              "description": "Parameters for the JSON-RPC method. Values can contain template expressions using ${...} syntax to reference other step results or context variables.",
              "additionalProperties": true
            }
          }
        }
      }
    },
    "TransformStep": {
      "type": "object",
      "description": "A step that performs data transformations using a series of operations.",
      "required": ["name", "transform"],
      "properties": {
        "transform": {
          "type": "object",
          "required": ["input", "operations"],
          "properties": {
            "input": {
              "oneOf": [
                {
                  "type": "string",
                  "description": "Expression that evaluates to the input data for transformation."
                },
                {
                  "type": "array",
                  "description": "Array literal to use as input for transformation.",
                  "items": {}
                }
              ]
            },
            "operations": {
              "type": "array",
              "description": "Sequence of operations to apply to the input data.",
              "items": {
                "type": "object",
                "required": ["type", "using"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "map",
                      "filter",
                      "reduce",
                      "flatten",
                      "sort",
                      "unique",
                      "group",
                      "join"
                    ],
                    "description": "The type of transformation operation to perform."
                  },
                  "using": {
                    "type": "string",
                    "description": "Expression defining the operation. For map/filter, this is evaluated for each item. For reduce, this combines items."
                  },
                  "as": {
                    "type": "string",
                    "description": "Optional variable name for the current item in the operation expression."
                  },
                  "initial": {
                    "description": "Initial value for reduce operations."
                  }
                }
              },
              "minItems": 1
            }
          }
        }
      }
    },
    "LoopStep": {
      "type": "object",
      "description": "A step that iterates over a collection and executes a nested step for each item.",
      "required": ["name", "loop"],
      "properties": {
        "loop": {
          "type": "object",
          "required": ["over", "as"],
          "properties": {
            "over": {
              "type": "string",
              "description": "Expression that evaluates to the array to iterate over."
            },
            "as": {
              "type": "string",
              "description": "Variable name to use for the current item in the iteration.",
              "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
            },
            "condition": {
              "type": "string",
              "description": "Optional condition to determine whether to execute the step for each item."
            },
            "maxIterations": {
              "type": "number",
              "description": "Optional maximum number of iterations to perform."
            },
            "step": {
              "$ref": "#/definitions/Step",
              "description": "The step to execute for each item in the iteration. Can be any primitive step type."
            },
            "steps": {
              "type": "array",
              "description": "An array of steps to execute for each item in the iteration.",
              "items": {
                "$ref": "#/definitions/Step"
              }
            }
          }
        }
      }
    },
    "ConditionStep": {
      "type": "object",
      "description": "A step that conditionally executes one of two possible steps based on a condition.",
      "required": ["name", "condition"],
      "properties": {
        "condition": {
          "type": "object",
          "required": ["if", "then"],
          "properties": {
            "if": {
              "type": "string",
              "description": "Expression that evaluates to a boolean determining which step to execute."
            },
            "then": {
              "$ref": "#/definitions/Step",
              "description": "Step to execute if the condition is true."
            },
            "else": {
              "$ref": "#/definitions/Step",
              "description": "Optional step to execute if the condition is false."
            }
          }
        }
      }
    },
    "StopStep": {
      "type": "object",
      "description": "A step that signals to end the workflow, with options to end the entire workflow or just the current branch.",
      "required": ["name", "stop"],
      "properties": {
        "name": {
          "type": "string",
          "description": "A unique identifier for the step within the flow. Used for referencing step results in expressions.",
          "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
        },
        "stop": {
          "type": "object",
          "required": ["endWorkflow"],
          "properties": {
            "endWorkflow": {
              "type": "boolean",
              "description": "Indicates whether to end the entire workflow (true) or just the current branch (false).",
              "default": true
            }
          }
        }
      }
    }
  }
}
