{
    "$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
                        }
                    }
                }
            }
        }
    }
}
