{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://openwop.dev/spec/v2/envelopes/ui.a2ui-surface.schema.json",
  "title": "UiA2uiSurfacePayload",
  "description": "Payload for the OPTIONAL, advertised `ui.a2ui-surface` AI Envelope kind (RFC 0102). Carries a declarative A2UI interface surface — a closed component tree the consumer renders with native widgets, routing user actions back to the producing agent WITHOUT executing any agent-supplied code. `ui.*` is a core, un-namespaced content-primitive family beside `media.*` (ai-envelope.md §\"A2UI surfaces\" / §\"Vendor-namespaced kinds\"). Not one of the four MUST-recognize universal kinds; an unrecognizing consumer falls back to store-without-render. Two per-kind schema versions (RFC 0209 §A): version 1 (or 0/absent) = `$defs/payloadV1`, the RFC 0102 seven-component tree pinned by `catalogVersion`; version 2 = `$defs/payloadV2`, an ordered run of A2UI v0.9 server-to-client messages restricted to the OpenWOP profile of the basic catalog (spec/v2/ext/a2uiSurface/README.md). An engine validates against the ONE branch the version selects (events.md §\"The envelope-kind catalog\"), never the union; the `anyOf` exists for tooling. Every payloadV2 message is also a valid upstream A2UI v0.9 message (RFC 0209 §B.4).",
  "anyOf": [
    {
      "$ref": "#/$defs/payloadV1"
    },
    {
      "$ref": "#/$defs/payloadV2"
    }
  ],
  "$defs": {
    "payloadV1": {
      "type": "object",
      "description": "Per-kind schema version 1 (or 0/absent): the RFC 0102 seven-component tree pinned by `catalogVersion`, unchanged from the seeded root (RFC 0209 §A.1). Readers keep accepting it on replay, fork and poll for the life of the major (RFC 0209 §C.11).",
      "required": [
        "catalogVersion",
        "surface"
      ],
      "additionalProperties": false,
      "properties": {
        "reasoning": {
          "type": "string",
          "description": "OPTIONAL per RFC 0030 §A — the model's reasoning, conventionally the first property of a kind whose payload benefits from multi-step composition."
        },
        "catalogVersion": {
          "type": "string",
          "enum": [
            "0.9.1"
          ],
          "description": "REQUIRED — the A2UI catalog version the surface targets. This enum IS the host's supported-version set (ai-envelope.md §\"A2UI surfaces\"); it is never a free string the producer invents. A consumer MUST refuse an unknown/higher version with `unknown_schema_version`. Pinning the version in the payload keeps `:fork`/replay deterministic after the external A2UI standard ships a breaking version."
        },
        "surface": {
          "$ref": "#/$defs/surface",
          "description": "REQUIRED — the A2UI surface document: a closed component tree (ai-envelope.md §\"A2UI surfaces\"). Self-contained: renderable from the payload alone, never a live reference into an external catalog."
        }
      }
    },
    "payloadV2": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "version",
        "catalogId",
        "surfaceId",
        "messages"
      ],
      "description": "Per-kind schema version 2: an ordered run of A2UI v0.9 server-to-client messages for one surface, restricted to the OpenWOP profile of the basic catalog (RFC 0209 §A.2, §B). Every message's `surfaceId` MUST equal the payload's `surfaceId`, and a `createSurface.catalogId` MUST equal the payload's `catalogId`; the engine checks both cross-field rules at admission (spec/v2/ext/a2uiSurface/README.md).",
      "properties": {
        "reasoning": {
          "type": "string"
        },
        "version": {
          "type": "string",
          "enum": [
            "v0.9"
          ]
        },
        "catalogId": {
          "$ref": "#/$defs/catalogId"
        },
        "surfaceId": {
          "$ref": "#/$defs/surfaceId"
        },
        "messages": {
          "type": "array",
          "minItems": 1,
          "maxItems": 64,
          "items": {
            "$ref": "#/$defs/message"
          }
        }
      }
    },
    "binding": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "path"
      ],
      "properties": {
        "path": {
          "type": "string",
          "pattern": "^/",
          "maxLength": 512,
          "description": "A JSON Pointer into the surface's data model (A2UI v0.9 DataBinding)."
        }
      }
    },
    "dynString": {
      "description": "A2UI DynamicString, profiled: a literal or a data binding. FunctionCall values are excluded (RFC 0209 §B.4).",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 4096
        },
        {
          "$ref": "#/$defs/binding"
        }
      ]
    },
    "dynBool": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "$ref": "#/$defs/binding"
        }
      ]
    },
    "dynStringList": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 1024
          },
          "maxItems": 256
        },
        {
          "$ref": "#/$defs/binding"
        }
      ]
    },
    "dynValue": {
      "description": "A2UI DynamicValue, profiled: literal string/number/boolean/array or a binding; no FunctionCall.",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 4096
        },
        {
          "type": "number"
        },
        {
          "type": "boolean"
        },
        {
          "type": "array",
          "maxItems": 256
        },
        {
          "$ref": "#/$defs/binding"
        }
      ]
    },
    "componentId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9_.-]+$"
    },
    "accessibility": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "label": {
          "$ref": "#/$defs/dynString"
        },
        "description": {
          "$ref": "#/$defs/dynString"
        }
      }
    },
    "check": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "condition",
        "message"
      ],
      "description": "A2UI CheckRule, profiled to the pure `required` function only (RFC 0209 §B.4).",
      "properties": {
        "message": {
          "type": "string",
          "maxLength": 512
        },
        "condition": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "call",
            "args"
          ],
          "properties": {
            "call": {
              "type": "string",
              "enum": [
                "required"
              ]
            },
            "args": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "value"
              ],
              "properties": {
                "value": {
                  "$ref": "#/$defs/binding"
                }
              }
            },
            "returnType": {
              "type": "string",
              "enum": [
                "boolean"
              ]
            }
          }
        }
      }
    },
    "Text": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "text"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "Text"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "text": {
          "$ref": "#/$defs/dynString"
        },
        "variant": {
          "type": "string",
          "enum": [
            "h1",
            "h2",
            "h3",
            "h4",
            "h5",
            "caption",
            "body"
          ]
        }
      }
    },
    "TextField": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "label"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "TextField"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "checks": {
          "type": "array",
          "maxItems": 16,
          "items": {
            "$ref": "#/$defs/check"
          }
        },
        "label": {
          "$ref": "#/$defs/dynString"
        },
        "value": {
          "$ref": "#/$defs/dynString"
        },
        "variant": {
          "type": "string",
          "enum": [
            "longText",
            "number",
            "shortText"
          ],
          "description": "`obscured` is excluded: a surface MUST NOT solicit a secret (RFC 0209 §B.5; invariant a2ui-surface-no-secret-input)."
        },
        "validationRegexp": {
          "type": "string",
          "maxLength": 256
        }
      }
    },
    "CheckBox": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "label",
        "value"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "CheckBox"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "checks": {
          "type": "array",
          "maxItems": 16,
          "items": {
            "$ref": "#/$defs/check"
          }
        },
        "label": {
          "$ref": "#/$defs/dynString"
        },
        "value": {
          "$ref": "#/$defs/dynBool"
        }
      }
    },
    "ChoicePicker": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "options",
        "value"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "ChoicePicker"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "checks": {
          "type": "array",
          "maxItems": 16,
          "items": {
            "$ref": "#/$defs/check"
          }
        },
        "label": {
          "$ref": "#/$defs/dynString"
        },
        "variant": {
          "type": "string",
          "enum": [
            "multipleSelection",
            "mutuallyExclusive"
          ]
        },
        "options": {
          "type": "array",
          "minItems": 1,
          "maxItems": 256,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "label",
              "value"
            ],
            "properties": {
              "label": {
                "$ref": "#/$defs/dynString"
              },
              "value": {
                "type": "string",
                "maxLength": 1024
              }
            }
          }
        },
        "value": {
          "$ref": "#/$defs/dynStringList"
        },
        "displayStyle": {
          "type": "string",
          "enum": [
            "checkbox",
            "chips"
          ]
        },
        "filterable": {
          "type": "boolean"
        }
      }
    },
    "DateTimeInput": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "value"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "DateTimeInput"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "checks": {
          "type": "array",
          "maxItems": 16,
          "items": {
            "$ref": "#/$defs/check"
          }
        },
        "label": {
          "$ref": "#/$defs/dynString"
        },
        "value": {
          "$ref": "#/$defs/dynString"
        },
        "enableDate": {
          "type": "boolean"
        },
        "enableTime": {
          "type": "boolean"
        }
      }
    },
    "Button": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "child",
        "action"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "Button"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "child": {
          "$ref": "#/$defs/componentId"
        },
        "variant": {
          "type": "string",
          "enum": [
            "default",
            "primary",
            "borderless"
          ]
        },
        "action": {
          "$ref": "#/$defs/action"
        }
      }
    },
    "action": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "event"
      ],
      "description": "A2UI Action, profiled to the server-event arm only; `functionCall` (client-side functions, including `openUrl`) is excluded (RFC 0209 §B.3; invariant a2ui-action-confinement).",
      "properties": {
        "event": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "resume",
                "exchange"
              ],
              "description": "The host-allowlisted target: an interrupt resume or a conversation exchange."
            },
            "context": {
              "type": "object",
              "maxProperties": 64,
              "additionalProperties": {
                "$ref": "#/$defs/dynValue"
              }
            }
          }
        }
      }
    },
    "Column": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "children"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "Column"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "children": {
          "type": "array",
          "maxItems": 256,
          "items": {
            "$ref": "#/$defs/componentId"
          }
        },
        "justify": {
          "type": "string",
          "enum": [
            "start",
            "center",
            "end",
            "spaceBetween",
            "spaceAround",
            "spaceEvenly",
            "stretch"
          ]
        },
        "align": {
          "type": "string",
          "enum": [
            "center",
            "end",
            "start",
            "stretch"
          ]
        }
      }
    },
    "Row": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "children"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "Row"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "children": {
          "type": "array",
          "maxItems": 256,
          "items": {
            "$ref": "#/$defs/componentId"
          }
        },
        "justify": {
          "type": "string",
          "enum": [
            "center",
            "end",
            "spaceAround",
            "spaceBetween",
            "spaceEvenly",
            "start",
            "stretch"
          ]
        },
        "align": {
          "type": "string",
          "enum": [
            "start",
            "center",
            "end",
            "stretch"
          ]
        }
      }
    },
    "Card": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component",
        "child"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "Card"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "child": {
          "$ref": "#/$defs/componentId"
        }
      }
    },
    "Divider": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "component"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/componentId"
        },
        "component": {
          "type": "string",
          "enum": [
            "Divider"
          ]
        },
        "accessibility": {
          "$ref": "#/$defs/accessibility"
        },
        "weight": {
          "type": "number"
        },
        "axis": {
          "type": "string",
          "enum": [
            "horizontal",
            "vertical"
          ]
        }
      }
    },
    "component": {
      "description": "One component of the OpenWOP profile of the A2UI v0.9 basic catalog (RFC 0209 §B.2). anyOf with a single-string-enum `component` discriminator, every object closed.",
      "anyOf": [
        {
          "$ref": "#/$defs/Text"
        },
        {
          "$ref": "#/$defs/TextField"
        },
        {
          "$ref": "#/$defs/CheckBox"
        },
        {
          "$ref": "#/$defs/ChoicePicker"
        },
        {
          "$ref": "#/$defs/DateTimeInput"
        },
        {
          "$ref": "#/$defs/Button"
        },
        {
          "$ref": "#/$defs/Column"
        },
        {
          "$ref": "#/$defs/Row"
        },
        {
          "$ref": "#/$defs/Card"
        },
        {
          "$ref": "#/$defs/Divider"
        }
      ]
    },
    "createSurface": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "version",
        "createSurface"
      ],
      "properties": {
        "version": {
          "type": "string",
          "enum": [
            "v0.9"
          ]
        },
        "createSurface": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "surfaceId",
            "catalogId"
          ],
          "properties": {
            "surfaceId": {
              "$ref": "#/$defs/surfaceId"
            },
            "catalogId": {
              "$ref": "#/$defs/catalogId"
            },
            "theme": {
              "type": "object",
              "additionalProperties": false,
              "description": "Profiled: `iconUrl` is excluded (network egress, RFC 0209 §B.3).",
              "properties": {
                "primaryColor": {
                  "type": "string",
                  "pattern": "^#[0-9a-fA-F]{6}$"
                },
                "agentDisplayName": {
                  "type": "string",
                  "maxLength": 128
                }
              }
            }
          }
        }
      }
    },
    "updateComponents": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "version",
        "updateComponents"
      ],
      "properties": {
        "version": {
          "type": "string",
          "enum": [
            "v0.9"
          ]
        },
        "updateComponents": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "surfaceId",
            "components"
          ],
          "properties": {
            "surfaceId": {
              "$ref": "#/$defs/surfaceId"
            },
            "components": {
              "type": "array",
              "minItems": 1,
              "maxItems": 512,
              "items": {
                "$ref": "#/$defs/component"
              }
            }
          }
        }
      }
    },
    "updateDataModel": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "version",
        "updateDataModel"
      ],
      "properties": {
        "version": {
          "type": "string",
          "enum": [
            "v0.9"
          ]
        },
        "updateDataModel": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "surfaceId"
          ],
          "properties": {
            "surfaceId": {
              "$ref": "#/$defs/surfaceId"
            },
            "path": {
              "type": "string",
              "pattern": "^/",
              "maxLength": 512
            },
            "value": {}
          }
        }
      }
    },
    "deleteSurface": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "version",
        "deleteSurface"
      ],
      "properties": {
        "version": {
          "type": "string",
          "enum": [
            "v0.9"
          ]
        },
        "deleteSurface": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "surfaceId"
          ],
          "properties": {
            "surfaceId": {
              "$ref": "#/$defs/surfaceId"
            }
          }
        }
      }
    },
    "message": {
      "anyOf": [
        {
          "$ref": "#/$defs/createSurface"
        },
        {
          "$ref": "#/$defs/updateComponents"
        },
        {
          "$ref": "#/$defs/updateDataModel"
        },
        {
          "$ref": "#/$defs/deleteSurface"
        }
      ]
    },
    "surfaceId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9_.:-]+$"
    },
    "catalogId": {
      "type": "string",
      "enum": [
        "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json"
      ],
      "description": "The host-pinned catalog set (RFC 0209 §B.1). Never a free string."
    },
    "surface": {
      "type": "object",
      "required": [
        "components"
      ],
      "additionalProperties": false,
      "properties": {
        "title": {
          "type": "string",
          "description": "OPTIONAL display title for the surface."
        },
        "components": {
          "type": "array",
          "description": "The flat, ordered component list. Each element is one of the host's day-1 catalog components, discriminated by the single-string-enum `component` field. `anyOf` (not `oneOf`) per ai-envelope.md §\"Schema discipline\".",
          "items": {
            "$ref": "#/$defs/componentV1"
          }
        }
      }
    },
    "componentV1": {
      "description": "A single A2UI component. Closed set (day-1 catalog 0.9.1); the `component` discriminator is a single-string-enum per branch.",
      "anyOf": [
        {
          "$ref": "#/$defs/heading"
        },
        {
          "$ref": "#/$defs/text"
        },
        {
          "$ref": "#/$defs/fieldText"
        },
        {
          "$ref": "#/$defs/fieldDate"
        },
        {
          "$ref": "#/$defs/fieldSelect"
        },
        {
          "$ref": "#/$defs/fieldCheckbox"
        },
        {
          "$ref": "#/$defs/actionButton"
        }
      ]
    },
    "heading": {
      "type": "object",
      "required": [
        "component",
        "text"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "heading"
          ]
        },
        "text": {
          "type": "string"
        },
        "level": {
          "type": "integer",
          "minimum": 1,
          "maximum": 6
        }
      }
    },
    "text": {
      "type": "object",
      "required": [
        "component",
        "text"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "text"
          ]
        },
        "text": {
          "type": "string"
        }
      }
    },
    "fieldText": {
      "type": "object",
      "required": [
        "component",
        "id",
        "label"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "field.text"
          ]
        },
        "id": {
          "type": "string",
          "description": "Binding key; the collected value is keyed by `id` in the resume value."
        },
        "label": {
          "type": "string"
        },
        "placeholder": {
          "type": "string"
        },
        "required": {
          "type": "boolean"
        }
      }
    },
    "fieldDate": {
      "type": "object",
      "required": [
        "component",
        "id",
        "label"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "field.date"
          ]
        },
        "id": {
          "type": "string"
        },
        "label": {
          "type": "string"
        },
        "required": {
          "type": "boolean"
        }
      }
    },
    "fieldSelect": {
      "type": "object",
      "required": [
        "component",
        "id",
        "label",
        "options"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "field.select"
          ]
        },
        "id": {
          "type": "string"
        },
        "label": {
          "type": "string"
        },
        "required": {
          "type": "boolean"
        },
        "options": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": [
              "value",
              "label"
            ],
            "additionalProperties": false,
            "properties": {
              "value": {
                "type": "string"
              },
              "label": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "fieldCheckbox": {
      "type": "object",
      "required": [
        "component",
        "id",
        "label"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "field.checkbox"
          ]
        },
        "id": {
          "type": "string"
        },
        "label": {
          "type": "string"
        },
        "default": {
          "type": "boolean"
        }
      }
    },
    "actionButton": {
      "type": "object",
      "required": [
        "component",
        "id",
        "label",
        "action"
      ],
      "additionalProperties": false,
      "properties": {
        "component": {
          "type": "string",
          "enum": [
            "action.button"
          ]
        },
        "id": {
          "type": "string"
        },
        "label": {
          "type": "string"
        },
        "action": {
          "type": "object",
          "required": [
            "target"
          ],
          "additionalProperties": false,
          "description": "Confined action (ai-envelope.md §\"A2UI surfaces\" rule 2). `target` resolves to exactly one host-allowlisted destination — a run interrupt resume or a conversation exchange — never an arbitrary URL, endpoint, or network egress. Enforced by the `a2ui-action-confinement` + `a2ui-surface-no-network-egress` SECURITY invariants.",
          "properties": {
            "target": {
              "type": "string",
              "enum": [
                "resume",
                "exchange"
              ],
              "description": "`resume` → the collected field values become the interrupt `resumeValue` (interrupt.md). `exchange` → the values become a conversation exchange message (RFC 0005)."
            }
          }
        }
      }
    }
  }
}
